python協程初步--gevent庫使用以及解釋什么是猴子補丁monkey_patch


協程工作的特點是遇到阻塞或耗時的任務時就切換,協程的生存依賴於線程,線程依賴於進程

  • 一個似乎有點問題的例子
import gevent,time

def kisscpc(num):
    for i in range(num):
        print ("吻了第%s下陳培昌"%(i+1),gevent.getcurrent())
    time.sleep(1)

def kisscj(num):
    for i in range(num):
        print ("吻了第%s下程勁"%(i+1),gevent.getcurrent())
    time.sleep(1)

def kissxxd(num):
    for i in range(num):
        print ("吻了第%s下徐曉冬"%(i+1),gevent.getcurrent())
    time.sleep(1)

g1 = gevent.spawn(kisscj,3)
g2 = gevent.spawn(kisscpc,2)
g3 = gevent.spawn(kissxxd,5)
g1.join()
g2.join()
g3.join()

輸出結果:

吻了第1下程勁 <Greenlet at 0x7fe77eed7648: kisscj(3)>
吻了第2下程勁 <Greenlet at 0x7fe77eed7648: kisscj(3)>
吻了第3下程勁 <Greenlet at 0x7fe77eed7648: kisscj(3)>
吻了第1下陳培昌 <Greenlet at 0x7fe77eed7a48: kisscpc(2)>
吻了第2下陳培昌 <Greenlet at 0x7fe77eed7a48: kisscpc(2)>
吻了第1下徐曉冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第2下徐曉冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第3下徐曉冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第4下徐曉冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>
吻了第5下徐曉冬 <Greenlet at 0x7fe77eed7b48: kissxxd(5)>

貌似這樣的結果並未能達到我們所期待的並發效果,任務仍舊是按部就班的執行。答案在於使用gevent時,相關的一切都要更換成gevent的

  • 耗時,阻塞部分換成gevent庫的實現
import gevent,time def kisscpc(num): for i in range(num): print ("吻了第%s下陳培昌"%(i+1),gevent.getcurrent()) #time.sleep(1) gevent.sleep(1) def kisscj(num): for i in range(num): print ("吻了第%s下程勁"%(i+1),gevent.getcurrent()) #time.sleep(1) gevent.sleep(1) def kissxxd(num): for i in range(num): print ("吻了第%s下徐曉冬"%(i+1),gevent.getcurrent())    #time.sleep(1) gevent.sleep(1) g1 = gevent.spawn(kisscj,3) g2 = gevent.spawn(kisscpc,2) g3 = gevent.spawn(kissxxd,5) g1.join() g2.join() g3.join()

輸出結果:

吻了第1下程勁 <Greenlet at 0x7f2af804e648: kisscj(3)>
吻了第1下陳培昌 <Greenlet at 0x7f2af804ea48: kisscpc(2)>
吻了第1下徐曉冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第2下程勁 <Greenlet at 0x7f2af804e648: kisscj(3)>
吻了第2下陳培昌 <Greenlet at 0x7f2af804ea48: kisscpc(2)>
吻了第2下徐曉冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第3下程勁 <Greenlet at 0x7f2af804e648: kisscj(3)>
吻了第3下徐曉冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第4下徐曉冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>
吻了第5下徐曉冬 <Greenlet at 0x7f2af804eb48: kissxxd(5)>

喲比~這才是我們期盼的!

但是,對於一些早期的代碼,每個任務的耗時部分仍有可能采用了常規的代碼寫法(而不是gevent.方法名),這就意味着,我們需要改動代碼的絕大多數部分

這時,猴子補丁就派上用場了

import gevent,time from gevent import monkey monkey.patch_all() def kisscpc(num): for i in range(num): print ("吻了第%s下陳培昌"%(i+1),gevent.getcurrent()) time.sleep(1) #gevent.sleep(1) def kisscj(num): for i in range(num): print ("吻了第%s下程勁"%(i+1),gevent.getcurrent()) time.sleep(1) #gevent.sleep(1) def kissxxd(num): for i in range(num): print ("吻了第%s下徐曉冬"%(i+1),gevent.getcurrent()) time.sleep(1) #gevent.sleep(1) g1 = gevent.spawn(kisscj,3) g2 = gevent.spawn(kisscpc,2) g3 = gevent.spawn(kissxxd,5) g1.join() g2.join() g3.join()

輸出結果:

吻了第1下程勁 <Greenlet at 0x7f97e4981948: kisscj(3)>
吻了第1下陳培昌 <Greenlet at 0x7f97e4981a48: kisscpc(2)>
吻了第1下徐曉冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第2下程勁 <Greenlet at 0x7f97e4981948: kisscj(3)>
吻了第2下陳培昌 <Greenlet at 0x7f97e4981a48: kisscpc(2)>
吻了第2下徐曉冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第3下程勁 <Greenlet at 0x7f97e4981948: kisscj(3)>
吻了第3下徐曉冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第4下徐曉冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>
吻了第5下徐曉冬 <Greenlet at 0x7f97e4981b48: kissxxd(5)>

我們看到僅僅用了monkey.patch_all()就達到了期待的效果,而其他方面幾乎沒什么改變

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM