8.16. 總結

你已走過 asyncio 的 API——在單一 CPU 上並行執行多項工作所需的各個部分:

  • 協作式排程 ——本模組其餘部分所立基的模型。正在執行的協程獨佔事件迴圈,直到它 await;切換只會發生在那些 await 處。

  • 協程與任務 —— async def 定義一個工作單元;asyncio.create_task() 並行排程一個工作單元,並回傳一個 Task,應用程式稍後可對其等待、取消或辨識。

  • 事件迴圈 ——執行協程與任務的引擎。asyncio.run() 是大多數指令碼唯一需要的進入點;Loop 類別為極少數需要的情況揭露了其餘功能。

  • 協調 ——gather() 用於扇出與扇入,wait_for() 用於設定期限,Task.cancelfinally 子句的清理模式,例外透過任務與 gather 呼叫傳播,以及事件迴圈的例外處理常式掛勾。

  • 同步原語 ——Event 用於協程之間的訊號傳遞,Lock 用於跨越多個 await 將對共享資源的存取序列化,以及 ThreadSafeFlag 用於從中斷處理常式喚醒 asyncio 任務。

  • 自訂非同步物件 ——讓應用程式類別得以接入 asyncio 慣用法的語言掛勾。__await__ 用於本身即為 await 對象的物件,__aiter__ / __anext__ 用於 async for__aenter__ / __aexit__ 用於 async with

  • 影格擷取 ——將 csi.CSI.snapshot() 轉換為對 await 友善的協程的包裝器,使擷取迴圈得以與其他 asyncio 工作並行執行。

  • 陷阱 ——遺漏的 await、沒有讓步的緊密迴圈、被吞掉的取消、跨越多個 await 被變動的共享狀態,以及其餘 asyncio 特有的陷阱。

這已足以撰寫在同一個事件迴圈上混合相機工作、硬體 I/O 與並行背景工作的程式。

8.16.1. 日後使用本參考

請將 asyncio 各章視為參考資料;為了查閱 async with 的形式,或 gather() 在某個兄弟任務失敗時的確切行為而回頭翻閱,正是其預期用途。asyncio 參考頁面在一個地方列出了每個函式與類別,適合用於「這個呼叫的確切名稱是什麼」這類問題。

若需要建立在本模組之上的更豐富原語——號誌、佇列、屏障,以及一大批應用導向的輔助工具——peterhinch/micropython-async 程式庫是社群維護的標準來源。

8.16.2. 接下來該往哪走

網路 是下一個主要主題。asyncio.open_connection()asyncio.start_server()Stream 類別,正是 asyncio 指令碼從協程內部與網路其餘部分溝通的方式,並搭配其底層的 networksocket 模組。你所學到關於 awaitTask、取消與同步原語的一切,都可直接沿用。