loop除了處理協程間的切換與結束時的異常捕捉,還要監聽socket和文件描述符。先作個小測試:bash
>>> import asyncio >>> loop = asyncio.get_event_loop() >>> loop2 = asyncio.get_event_loop() >>> loop is loop2 True # 兩個loop實例是徹底相同的
這意味着在一個coroutine內部獲取loop,也能夠經過asyncio.get_event_loop()
來獲得,並不須要將loop做爲參數傳遞給協程函數。對於框架設計者來講狀況又不一樣了,最好在函數設計中接受一個loop參數,以防止用戶使用loop策略來作一些額外的事情。框架
注意
get_event_loop()
方法僅在一樣的線程中生效,若是在一個新線程中,應該用new_event_loop()
來獲取新的loop,並經過set_event_loop(loop)
來將其設爲該線程下的loop。socket
若是在一個coroutine函數中建立tasks而不await它們,會發生什麼?事實上它們將獨立於這個coroutine函數內的執行上下文來運行,這個coroutine函數將會在它啓動的任務完成以前退出。async
async def f(): loop = asyncio.get_event_loop() for i in range(5): loop.create_task(<coro>)
像上述狀況,有時會在代碼中看到loop變量,而後create_task()
才能被調用,另外一種解決方案是使用asyncio.ensure_future()
方法,這個方法不須要經過loop來調用。函數
async def f(): for i in range(5): asyncio.ensure_future(<coro>)
或能夠經過輔助函數來作到。oop
def create_task(coro): return asyncio.get_event_loop().create_task(coro) async def f(): for i in range(5): create_task(<coro>)
loop.create_task()
和asyncio.ensure_future()
對初學者來講是很微妙和困惑的,下一章討論其中的差別。測試