協程技術

基礎概念

1.定義:纖程,微線程。是爲非搶佔式多任務產生子程序的計算機組件。協程容許不一樣入口點在不一樣位置暫停或開始,簡單來講,協程就是能夠暫停執行的函數。python

2.協程原理 : 記錄一個函數的上下文棧幀,協程調度切換時會將記錄的上下文保存,在切換回來時進行調取,恢復原有的執行內容,以便從上一次執行位置繼續執行。併發

3.協程優缺點異步

優勢:socket

  1. 協程完成多任務佔用計算資源不多
  2. 因爲協程的多任務切換在應用層完成,所以切換開銷少
  3. 協程爲單線程程序,無需進行共享資源同步互斥處理

缺點:協程的本質是一個單線程,沒法利用計算機多核資源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]) # 阻塞等待[]中的協成結束
gevent 協程示例
 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()
基於協程的tcp併發

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()

注意:腳本運行函數須要在對應模塊導入前執行

相關文章
相關標籤/搜索