python—协程
1、為什么要使用協程?
在執行A函數的時候,可以隨時中斷,去執行B函數,然后中斷執行A函數(可以自動切換),注意這一過程并不是函數調用(沒有調用語句),過程很像多線程,然而協程只有一個線程在執行。
2、協程的標準
:
a、必須在只有一個單線程里實現并發
b、修改共享數據不需要加鎖
c、用戶程序里自己保存多個控制流的上下文棧
d、一個協程遇到IO操作自動切換到其他協程
3、協程之Greenlet
from greenlet import greenlet# 開發協程的案例,一個任務是回答,一個任務是問def ask(name):print(f'{name}:你好啊') # 2b.switch('呂布') # todo answer函數第一次切換,需要傳參print(f'{name}:今天學習了嗎?') # 4b.switch()def answer(name):print(f'{name}:你也好啊') # 3a.switch()print(f'{name}:必須的')if __name__ == '__main__':# 創建2個協程a = greenlet(ask) # 創建第1個協程b = greenlet(answer) # 創建第2個協程a.switch('貂蟬') # todo 每個函數只有在第一次切換的時候,才需要傳參,后面不需要 UDP客戶端執行結果:
4、協程之Gevent
Gevent是一個第三方庫,可以輕松通過gevent 實現并發同步或異步編程,在gevent中用到的主要模式是Greenlet,它是以C擴展模塊形式接入Python的輕量級協程。Greenlet 全部運行在主程序操作系統進程的內部,但他們被協作式地調度。
當一個greenlet遇到O操作時,比如訪問網絡/睡眠等待,就自動切換到其他的greenlet,等到IO操作完成,再在適當的時候切換回來繼續執行。由于I0操作非常耗時,經常使程序處于等待狀態,有了gevent為我們自動切換協程,就保證總有greenlet在運行,而不是等待I0。同時也因為只有一個線程在執行,會極大的減少上下文切換的成本。
注意:上例gevent.sleep(2)模擬的是gevent可以識別的io阻塞;而time.sleep(2)或其他的阻塞,gevent,是不能直接識別的,需要加入一行代monkey.patch_all(),這行代碼需在time,socket模塊之前。
執行結果:
5、協程之asyncio
import asyncioasync def func1(): # 定義一個協程for i in range(5):print('協程a!!!')await asyncio.sleep(1) # 人為的模擬IO阻塞async def func2(): # 定義一個協程for i in range(5):print('協程b!!!')await asyncio.sleep(2)# todo 獲取循環的事件 loop = asyncio.get_event_loop()# todo 啟動多個協程并行執行 loop.run_until_complete(asyncio.gather(func1(), func2()))loop.close()執行結果:
總結
- 上一篇: python操作mysql操作步骤
- 下一篇: MySQL—视图(二)