8.13. 迴圈控制

大多數 asyncio 指令碼從不直接接觸事件迴圈 -- asyncio.run() 就已足夠。本頁面涵蓋 Loop 介面,以因應它不足的情況:安裝例外處理器、以不同於 run 的生命週期執行迴圈,或保留迴圈物件以進行檢測。

8.13.1. 取得迴圈

  • asyncio.get_event_loop() -- 回傳 Loop 物件。從協程內部或外部呼叫都是安全的。

  • asyncio.new_event_loop() -- 在 MicroPython 上,這會重設現有迴圈的狀態,而非建立一個新迴圈。這點值得再次強調:每個程式恰好只有一個事件迴圈。

除了 Loop 上的方法與 asyncio.run() 之外,並沒有用於執行迴圈的 API。

8.13.2. 直接執行迴圈

asyncio.run() 是幾乎每個應用程式正確的進入點。有兩個 Loop 方法是為了它不足的情況而存在。

  • run_until_complete() -- 給定一個可等待物件,執行迴圈直到該可等待物件完成,然後回傳其結果。相當於單次 asyncio.run() 呼叫,但省去了迴圈的拆除工作。

  • run_forever() -- 執行迴圈,直到從某個任務內部呼叫 stop() 為止。沒有頂層的可等待物件;應用程式應在呼叫 run_forever 之前,透過 asyncio.create_task() 排程所需的一切。

搭配的方法是 stop()(要求迴圈在目前任務完成後停止)與 close()(釋放迴圈的資源)。

8.13.3. 迴圈端的任務建立

  • create_task() -- 與 asyncio.create_task() 是相同的操作。獨立函式之所以存在,是為了讓應用程式碼在常見情況下不需要迴圈參考;而方法之所以存在,是為了已經持有迴圈參考的檢測程式碼。

8.13.4. 例外處理器

當某個任務引發了協程呼叫鏈中無人捕捉的例外時,迴圈會呼叫處理器 -- 典型的情況是應用程式以 asyncio.create_task() 建立卻從未 await 的任務。預設處理器會透過 sys.stderr 印出回溯訊息;例外 頁面已說明過如何將它替換成自訂的版本。

  • set_exception_handler() -- 安裝自訂處理器。處理器是一個可呼叫物件 handler(loop, context),其中 context 是一個字典,至少包含 'message',通常還包含 'exception''future'

  • get_exception_handler() -- 回傳目前已安裝的處理器,若正在使用預設處理器則回傳 None

  • default_exception_handler() -- 內建處理器。當自訂處理器希望同時執行預設行為時很有用(例如同時記錄到 flash 印出回溯訊息)。

  • call_exception_handler() -- 以手動建構的 context 字典執行目前已安裝的處理器。主要由迴圈本身使用;應用程式很少需要它。