asyncio是Python 3.4版本引入的標準函式庫,直接內建了對非同步IO的支援。 asyncio的程式模型就是一個訊息循環。今天我們就來詳細討論下asyncio 中的coroutine 與Future對象
#">
coroutine 與Future 的關係
##看起來兩者是一樣的,因為都可以用以下的語法來非同步取得結果,
result = await future result = await coroutine
實際上,coroutine 是生成器函數,它既可以從外部接受參數,也可以產生結果。時間內,我們可以切換到其他任務繼續執行。 。實際結果。
tasks = asyncio.gather( asyncio.ensure_future(func1()), asyncio.ensure_future(func2()) ) loop.run_until_complete(tasks)
和tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]
loop.run_until_complete(asyncio.wait(tasks))
ensure_future 可以將coroutine 封裝成Task。 run_until_complete 既可以接收Future 對象,也可以是coroutine 對象,
BaseEventLoop.run_until_complete(future) Run until the Future is done. If the argument is a coroutine object, it is wrapped by ensure_future(). Return the Future's result, or raise its exception.
Task 任務的正確
退出方式
在asyncio 的任務循環中,如果使用CTRL-C 退出的話,即使捕獲了異常,Event Loop 中的任務會報錯,出現如下的錯誤,
Task was destroyed but it is pending!
task:for
=a result / exception are available, or that the future was cancelled
Task 物件的cancel 和其父類Future 略有不同。當呼叫 Task.cancel() 後,對應 coroutine 會在事件
循環的下一輪中拋出 CancelledError 例外。使用 Future.cancelled() 並不能立即返回 True(用來表示任務結束),只有在上述異常被處理任務結束後才算是 cancelled。
故結束任務可以用for task in asyncio.Task.all_tasks():
task.cancel()
這種方法將所有任務找出並 cancel。
但CTRL-C 也會將事件循環停止,所以有必要重新啟動事件循環,
try: loop.run_until_complete(tasks) except KeyboardInterrupt as e: for task in asyncio.Task.all_tasks(): task.cancel() loop.run_forever() # restart loop finally: loop.close()
在每個Task 中捕獲異常是必要的,如果不確定,可以使用
asyncio.gather(..., return_exceptions=True)將例外轉換為正常的結果回傳。
以上是詳解asyncio的coroutine物件與Future物件使用方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!