python asyncio筆記

1.什麼是coroutinehtml

coroutine,最先我是在lua裏面看到的,coroutine最大的好處是能夠保存堆棧,讓程序得以繼續執行,在python裏面,通常是利用yield來實現,具體能夠看以下文章:python

http://www.cnblogs.com/tqsummer/archive/2010/12/27/1917927.htmlwindows

 

python中的yield以及yield from語法可讓程序支持coroutine服務器

 

2.asyncio異步

Python3中,提供了基於coroutine的異步IO庫,就是asynciosocket

https://docs.python.org/3/library/asyncio.htmlasync

 

2.1 event looptcp

asyncio庫一個重要的概念就是事件循環,只有啓動事件循環之後,纔可讓coroutine任務得以繼續執行,若是event loop中止或者暫停,那麼整個異步io也中止或者暫停,相似於操做系統的事件循環機制函數

asyncio的內部是基於selector(也多是epoll)或者windows iocp來實現的,這也是爲何須要啓動一個event loopevent loop能夠當作是對各個平臺的異步IO"等待"這個操做的封裝工具

 

2.2 asyncio

cotoutine

coroutine即爲一個支持寫成的函數,能夠利用iscoroutinefunction來判斷是否coroutine函數,這個函數須要@asyncio.coroutine來修飾

利用@asyncio.coroutine修飾之後,這個函數能夠支持await(python 3.5) 或者 yield from語法,一旦執行yield from 語法之後,asyncio將會掛起當前的coroutine,去執行其餘的coroutine

 

以下代碼:

 

當開始運行event loop之後

1.開始執行sleep3s

2.當程序開始進入睡眠之後,event loop不會中止當前線程,而是掛起當前函數,執行下一個coroutine,sleep5s

3.sleep5s開始進入睡眠,掛起當前的函數

4.event loop檢測到sleep 3s時間已經到了,因而從新執行被掛起的sleep3s,sleep3s執行完畢

5.sleep5s時間已經到了,因而從新執行被掛起的sleep5s,sleep5s執行完畢

 

基於coroutine的服務器

 

 

如上圖,_tcp_listen建立了一個tcp 服務器,而且收到一個tcp連接之後,建立一個_tcp_recv的任務,而後開始監聽tcp鏈接的數據

 

與基於回調的庫區別

coroutine版本代碼在recv上邏輯處理代碼是線性的而不是斷裂的,基於回調的代碼則常常須要亂跳,可讀性較高

並且不用建立臨時的數據去保存一些變量,上圖中的self.tcp_clients就是由於老版本是基於回調的,須要這個數據成員去存儲(懶得再本身從新寫代碼,這分是重構某個工具到通常時候的代碼)

 

擴展asyncio

 

由於項目裏面須要知道對方udp的地址,所以須要擴展sock_recv,利用socket自己提供的recv_from

看了下loop.socket_recv的源碼,loop.socket_recv

 

 

 

在調用以前 必須將socket設置爲非阻塞,不然會報錯

關鍵點在於add_reader這個函數將socket傳送給異步IO(默認是selector),而且傳送一個回調進去(在這個例子裏面是_sock_recv本身這個函數,只要有數據能夠讀取之後,將會再次調用_sock_recv這個函數

 

asyncio也不止支持sleep以及io操做,還支持多進程,lock等操做

 

只要將上圖的data = sock.recv(n)改成data, addr = sock.recv_from(n)就能夠了

 

3.5中,新增長了async以及await的語法,用於代替asynio.coroutine以及yield from

Python3.5 async以及await

https://www.python.org/dev/peps/pep-0492/

相關文章
相關標籤/搜索