基礎概念
1.定義:纖程,微線程。是爲非搶佔式多任務產生子程序的計算機組件。協程容許不一樣入口點在不一樣位置暫停或開始,簡單來講,協程就是能夠暫停執行的函數。python
2.協程原理 : 記錄一個函數的上下文棧幀,協程調度切換時會將記錄的上下文保存,在切換回來時進行調取,恢復原有的執行內容,以便從上一次執行位置繼續執行。併發
3.協程優缺點異步
優勢:socket
- 協程完成多任務佔用計算資源不多
- 因爲協程的多任務切換在應用層完成,所以切換開銷少
- 協程爲單線程程序,無需進行共享資源同步互斥處理
缺點:協程的本質是一個單線程,沒法利用計算機多核資源async
標準庫協程的實現
python3.5之後,使用標準庫asyncio和async/await 語法來編寫併發代碼。asyncio庫經過對異步IO行爲的支持完成python的協程。雖然官方說asyncio是將來的開發方向,可是因爲其生態不夠豐富,大量的客戶端不支持awaitable須要本身去封裝,因此在使用上存在缺陷。更多時候只能使用已有的異步庫(asyncio等),功能有限。tcp
第三方協程模
1.greenlet模塊ide
安裝 : sudo pip3 install greenlet函數
函數spa
greenlet.greenlet(func)線程
- 功能:建立協程對象
- 參數:協程函數
g.switch()
- 功能:選擇要執行的協程函數


1 from greenlet import greenlet 2 3 def test1(): 4 print("執行test1") 5 gr2.switch() 6 print("結束test1") 7 gr2.switch() 8 9 def test2(): 10 print("執行test2") 11 gr1.switch() 12 print("結束test2") 13 14 # 將函數變成協程 15 gr1 = greenlet(test1) 16 gr2 = greenlet(test2) 17 gr1.switch() # 選擇執行協程1
2.gevent模塊
安裝:sudo pip3 install gevent
函數
gevent.spawn(func,argv)
- 功能: 生成協程對象
- 參數:
- func 協程函數
- argv 給協程函數傳參(不定參)
返回值: 協程對象
gevent.joinall(list,[timeout])
- 功能: 阻塞等待協程執行完畢
- 參數:
- list 協程對象列表
- timeout 超時時間
gevent.sleep(sec)
- 功能: gevent睡眠阻塞
- 參數:睡眠時間
gevent協程只有在遇到gevent指定的阻塞行爲時纔會自動在協程之間進行跳轉
如gevent.joinall(),gevent.sleep()帶來的阻塞


1 import gevent 2 3 4 # 協程函數 5 def foo(a,b): 6 print("Running foo ...",a,b) 7 gevent.sleep(2) 8 print("Foo again") 9 10 def bar(): 11 print("Running bar ...") 12 gevent.sleep(3) 13 print("bar again") 14 15 f = gevent.spawn(foo,1,2) 16 b = gevent.spawn(bar) 17 18 gevent.joinall([f,b]) # 阻塞等待[]中的協成結束


1 """ 2 擴展代碼 3 """ 4 5 import gevent 6 from gevent import monkey 7 monkey.patch_all() # 在導入socket前執行 8 from socket import * 9 10 # 處理客戶端請求 11 def handle(c): 12 while True: 13 data = c.recv(1024) 14 if not data: 15 break 16 print(data.decode()) 17 c.send(b'OK') 18 c.close() 19 20 # 建立TCP套接字 21 s = socket() 22 s.bind(('0.0.0.0',8888)) 23 s.listen(5) 24 while True: 25 c,addr = s.accept() 26 print("Connect from",addr) 27 # handle(c) # 循環方案 28 gevent.spawn(handle,c) # 協程方案 29 30 s.close()
monkey腳本
做用:在gevent協程中,協程只有遇到gevent指定類型的阻塞才能跳轉到其餘協程,所以,咱們但願將普通的IO阻塞行爲轉換爲能夠觸發gevent協程跳轉的阻塞,以提升執行效率。
轉換方法:gevent 提供了一個腳本程序monkey,能夠修改底層解釋IO阻塞的行爲,將不少普通阻塞轉換爲gevent阻塞。
使用方法:
1.導入monkey
from gevent import monkey
2.運行相應的腳本,例如轉換socket中全部阻塞
monkey.patch_socket()
3. 若是將全部可轉換的IO阻塞所有轉換則運行all
monkey.patch_all()
注意:腳本運行函數須要在對應模塊導入前執行