很多朋友對異步編程都處于“聽說很強大”的認知狀態。鮮有在生產項目中使用它。而使用它的同學,則大多數都停留在知道如何使用 Tornado、Twisted、Gevent 這類異步框架上,出現各種古怪的問題難以解決。而且使用了異步框架的部分同學,由于用法不對,感覺它并沒牛逼到哪里去,所以很多同學做 Web 后端服務時還是采用 Flask、Django等傳統的非異步框架。
從上兩屆 PyCon 技術大會看來,異步編程已經成了 Python 生態下一階段的主旋律。如新興的 Go、Rust、Elixir 等編程語言都將其支持異步和高并發作為主要“賣點”,技術變化趨勢如此。Python 生態為不落人后,從2013年起由 Python 之父 Guido 親自操刀主持了Tulip(asyncio)項目的開發。
異步io的好處在于避免的線程的開銷和切換,而且我們都知道python其實是沒有多線程的,只是通過底層線層鎖實現的多線程。另一個好處在于避免io操作(包含網絡傳輸)的堵塞時間。
asyncio可以實現單線程并發IO操作。如果僅用在客戶端,發揮的威力不大。如果把asyncio用在服務器端,例如Web服務器,由于HTTP連接就是IO操作,因此可以用單線程+coroutine實現多用戶的高并發支持。
asyncio實現了TCP、UDP、SSL等協議,aiohttp則是基于asyncio實現的HTTP框架。
對于異步io你需要知道的重點,要注意的是,await語法只能出現在通過async修飾的函數中,否則會報SyntaxError錯誤。而且await后面的對象需要是一個Awaitable,或者實現了相關的協議。注意:
所有需要異步執行的函數,都需要asyncio中的輪訓器去輪訓執行,如果函數阻塞,輪訓器就會去執行下一個函數。所以所有需要異步執行的函數都需要加入到這個輪訓器中。asyncio
asyncio的基本概念asyncio是在python3.4中被引進的異步IO庫。你也可以通過python3.3的pypi來安裝它。它相當的復雜,而且我不會介紹太多的細節。相反,我將會解釋你需要知道些什么,以利用它來寫異步的代碼。簡而言之,有兩件事情你需要知道:協同程序和事件循環。協同程序像是方法,但是它們可以在代碼中的特定點暫停和繼續。當在等待一個IO(比如一個HTTP請求),同時執行另一個請求的時候,可以用來暫停一個協同程序。
例如:
import requestsimport timeimport asyncio# 創建一個異步函數async def task_func(): await asyncio.sleep(1) resp = requests.get('http://192.168.2.177:5002/') print('2222222',time.time(),resp.text)async def main(loop): loop=asyncio.get_event_loop() # 獲取全局輪訓器 task = loop.create_task(task_func()) # 在全局輪訓器加入協成,只有加入全局輪訓器才能被監督執行 await asyncio.sleep(2) # 等待兩秒為了不要立即執行event_loop.close(),項目中event_loop應該是永不停歇的 print('11111111111',time.time())event_loop = asyncio.get_event_loop()try: event_loop.run_until_complete(main(event_loop))finally: event_loop.close() # 當輪訓器關閉以后,所有沒有執行完成的協成將全部關閉
新聞熱點
疑難解答