asyncio提供的架構以事件循環(event loop) 為中心,程式開啟一個無限的循環,程式會把一些函數注冊到事件循環上。當滿足事件發生的時候,調用相應的協程函數。
事件循環loop調用方法loop.run_until_complete(…)驅動傳入的參數,它的參數是一個future或者協程。協程、future和任務(Task)都由yield from驅動,這正是run_until_complete方法對其參數所做的事情。
yield from function句法能夠防止阻塞,是因為目前協程(即包括yield from代碼的委派生成器)暫停後,控制權回到事件循環手中,再去驅動其它協程; function future或協程運作結束後,把結果傳回到暫停的協程(yield from自動捕獲StopIteration),将其恢複,即最外層的事件循環始終可以不被阻塞,并發地排程所有協程向前推進。
Future
future是一個資料結構,表示還未完成的工作結果。事件循環可以監視Future對象是否完成。進而允許應用的一部分等待另一部分完成一些工作。
Task
Task是Future的一個子類,它知道如何包裝和管理一個協程的執行。
await
await 用于挂起阻塞的異步調用,用于挂起耗時的操作。
使用await可以針對耗時的操作進行挂起,就像生成器裡的yield一樣,函數讓出控制權。協程遇到await,事件循環将會挂起該協程,執行await 後面跟着的那個協程,直到await來的協程也挂起或者執行完畢,再進行下一個協程的執行。
import asyncio
# async關鍵字定義一個協程(coroutine),協程也是一種對象。
# 協程不能直接運作,需要把協程加入到事件循環(loop)
async def func(n):
print('Hello world <{}>'.format(n))
r = await asyncio.sleep(n)
print('hello again <{}>'.format(n))
# asyncio.get_event_loop 方法可以建立一個事件循環。
loop = asyncio.get_event_loop()
# run_until_complete 将協程注冊到事件循環,并啟動事件循環。
# loop.run_until_complete(func(6))
tasks = [func(4), func(5), func(2)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
"""
Hello world <5>
Hello world <2>
Hello world <4>
hello again <2>
hello again <4>
hello again <5>
"""