协程:Greenlet模块、Gevent模块
生活随笔
收集整理的這篇文章主要介紹了
协程:Greenlet模块、Gevent模块
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
三、Greenlet模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
Greenlet是python的一個C擴展,來源于Stackless python,旨在提供可自行調度的‘微線程’, 即協程。generator實現的協程在yield value時只能將value返回給調用者(caller)。 而在greenlet中,target.switch(value)可以切換到指定的協程(target), 然后yield value。greenlet用switch來表示協程的切換,從一個協程切換到另一個協程需要顯式指定。安裝 :pip3 install greenlet 簡介: from greenlet import greenletdef eat(name):print('%s eat 1' %name)g2.switch('egon')print('%s eat 2' %name)g2.switch() def play(name):print('%s play 1' %name)g1.switch()print('%s play 2' %name)g1=greenlet(eat) g2=greenlet(play)g1.switch('egon')#可以在第一次switch時傳入參數,以后都不需要 greenlet實現狀態切換有幾個缺點
1.手動切換
2.不能規避I/O操作(睡眠)
?
gevent模塊?
安裝:pip3 install geventGevent 是一個第三方庫,可以輕松通過gevent實現并發同步或異步編程,在gevent中用到的主要模式是Greenlet, 它是以C擴展模塊形式接入Python的輕量級協程。 Greenlet全部運行在主程序操作系統進程的內部,但它們被協作式地調度。 介紹、安裝 g1=gevent.spawn(func,1,,2,3,x=4,y=5)創建一個協程對象g1,spawn括號內第一個參數是函數名,如eat,后面可以有多個參數,可以是位置實參或關鍵字實參,都是傳給函數eat的g2=gevent.spawn(func2)g1.join() #等待g1結束 g2.join() #等待g2結束#或者上述兩步合作一步:gevent.joinall([g1,g2]) g1.value#拿到func1的返回值#例:遇到io主動切換from gevent import monkey;monkey.patch_all()import gevent import time def eat():print('eat food 1')time.sleep(2)print('eat food 2')def play():print('play 1')time.sleep(1)print('play 2')g1=gevent.spawn(eat) g2=gevent.spawn(play) gevent.joinall([g1,g2]) print('主') 用法介紹 真正能實現協程的模塊geventimport gevent def eat():print('eating1')print('eating2') g1 = gevent.spawn(eat) #創建一個協程對象g1 #執行輸出為空,表示它還沒執行。import gevent def eat():print('eating1')print('eating2') g1 = gevent.spawn(eat) #創建一個協程對象g1 g1.join() #等待g1結束#執行輸出:#eating1 #eating2 例子geven 不能識別time.sleep()? 需要用gevent.sleep()? 或者導入一個模塊monkey;monkey patch (猴子補丁)
#如果想讓協程執行time.sleep()呢?由于默認,協程無法識別time.sleep()方法,需要導入一個模塊monkey#monkey patch (猴子補丁) #用來在運行時動態修改已有的代碼,而不需要修改原始代碼。from gevent import monkey;monkey.patch_all() # 它會把下面導入的所有的模塊中的IO操作都打成一個包,gevent就能夠認識這些IO了 import time import gevent def eat():print('eating1')time.sleep(1) #延時調用print('eating2')def play():print('playing1')time.sleep(1) #延時調用print('playing2')g1 = gevent.spawn(eat) #創建一個協程對象g1 g2 = gevent.spawn(play) g1.join() #等待g1結束 g2.join()#執行輸出: eating1 playing1 eating2 playing2 使用結論:
使用gevent模塊來執行多個函數,表示在這些函數遇到IO操作的時候可以在同一個線程中進行切換
利用其他任務的IO阻塞時間來切換到其他的任務繼續執行
前提是:
spawn來發布協程任務
join負責開啟并等待任務執行結束
gevent本身不認識其他模塊中的IO操作,但是如果我們在導入其他模塊之前執行from gevent import monkey;monkey.patch_all()? 這行代碼,必須在文件最開頭
gevent就能夠認識在這句話之后導入的模塊中的所有IO操作了
Gevent之同步與異步
from gevent import spawn,joinall,monkey;monkey.patch_all()import time def task(pid):"""Some non-deterministic task"""time.sleep(0.5)print('Task %s done' % pid)def synchronous(): # 同步for i in range(10):task(i)def asynchronous(): # 異步g_l=[spawn(task,i) for i in range(10)]joinall(g_l)print('DONE')if __name__ == '__main__':print('Synchronous:')synchronous()print('Asynchronous:')asynchronous() # 上面程序的重要部分是將task函數封裝到Greenlet內部線程的gevent.spawn。 # 初始化的greenlet列表存放在數組threads中,此數組被傳給gevent.joinall 函數, # 后者阻塞當前流程,并執行所有給定的greenlet任務。執行流程只會在 所有greenlet執行完后才會繼續向下走。 實例當一個任務執行時,依賴另外一個任務的結果時,這種情況不適合異步,只能用同步
Gevent之應用舉例一
Gevent之應用舉例二
轉載于:https://www.cnblogs.com/python-by-xiaoma/p/10300000.html
總結
以上是生活随笔為你收集整理的协程:Greenlet模块、Gevent模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 反网络爬虫以及解决方案
- 下一篇: P1351 联合权值