asyncio --- 非同步 I/O 排程器

本模組提供一個用於 async/await 協程的協作式多工排程器,並提供用於同步處理的基本元件(鎖、事件),以及透過串流讀取器與寫入器進行的非阻塞 TCP 網路功能。各項任務在單一事件迴圈上並行執行;目前執行中的任務透過 await 將控制權交還給迴圈。

範例::

import asyncio

async def blink(led, period_ms):
    while True:
        led.on()
        await asyncio.sleep_ms(5)
        led.off()
        await asyncio.sleep_ms(period_ms)

async def main(led1, led2):
    asyncio.create_task(blink(led1, 700))
    asyncio.create_task(blink(led2, 400))
    await asyncio.sleep_ms(10_000)

# Running on an OpenMV Cam
from machine import LED
asyncio.run(main(LED(1), LED(2)))

核心函式

asyncio.create_task(coro: Coroutine) Task

從給定的協程建立一個新任務並排程使其執行。

傳回對應的 Task 物件。

asyncio.current_task() Task

傳回與目前執行中任務相關聯的 Task 物件。

asyncio.run(coro: Coroutine) Any

從給定的協程建立一個新任務並執行它直到完成。

傳回 coro 所傳回的值。

asyncio.sleep(t: float) None

休眠 t 秒(可以是浮點數)。

這是一個協程。

asyncio.sleep_ms(t: int) None

休眠 t 毫秒。

這是一個協程,也是 MicroPython 的擴充功能。

其他函式

asyncio.wait_for(awaitable: Awaitable, timeout: float) Any

等待 awaitable 完成,但若耗時超過 timeout 秒則取消它。若 awaitable 不是任務,則會由它建立一個任務。

若發生逾時,則會取消該任務並引發 asyncio.TimeoutError:呼叫端應攔截此例外。該任務會收到 asyncio.CancelledError,可以忽略它,或使用 try...excepttry...finally 加以攔截以執行清理程式碼。

傳回 awaitable 的回傳值。

這是一個協程。

asyncio.wait_for_ms(awaitable: Awaitable, timeout: int) Any

wait_for() 類似,但 timeout 是以毫秒為單位的整數。

這是一個協程,也是 MicroPython 的擴充功能。

asyncio.gather(*awaitables, return_exceptions: bool = False) List

並行執行所有 awaitables。任何不是任務的 awaitables 都會被提升為任務。

傳回所有 awaitables 的回傳值清單。

這是一個協程。

class Task

class asyncio.Task

此物件將協程包裝成一個執行中的任務。可使用 await task 等待任務,這會等待任務完成並傳回該任務的回傳值。

不應直接建立任務,而應使用 create_task() 來建立它們。

cancel() None

藉由將 asyncio.CancelledError 注入任務來取消它。任務可以忽略此例外。可藉由攔截此例外,或透過 try ... finally 來執行清理程式碼。

class Event

class asyncio.Event

建立一個可用於同步任務的新事件。事件以已清除的狀態開始。

is_set() bool

若事件已設定則傳回 True,否則傳回 False

set() None

設定事件。任何等待此事件的任務都將被排程執行。

注意:此方法必須在任務內部呼叫。從 IRQ、排程器回呼函式或其他執行緒呼叫此方法並不安全。請參閱 ThreadSafeFlag

clear() None

清除事件。

wait() None

等待事件被設定。若事件已被設定則立即傳回。

這是一個協程。

class ThreadSafeFlag

class asyncio.ThreadSafeFlag

建立一個新旗標,可用於將任務與在 asyncio 迴圈外執行的程式碼(例如其他執行緒、IRQ 或排程器回呼函式)同步。旗標以已清除的狀態開始。

set() None

設定旗標。若有任務正在等待此旗標,它將被排程執行。

clear() None

清除旗標。這可用於確保在等待旗標前,先前可能已設定的旗標已被清除。

wait() None

等待旗標被設定。若旗標已被設定則立即傳回。從 wait 傳回時旗標會自動重設。

一次只能有單一任務等待某一旗標。

這是一個協程。

class Lock

class asyncio.Lock

建立一個可用於協調任務的新鎖。鎖以未鎖定的狀態開始。

除了下列方法外,鎖也可用於 async with 陳述式中。

locked() bool

若鎖已鎖定則傳回 True,否則傳回 False

acquire() bool

等待鎖處於未鎖定狀態,然後以不可分割的方式將其鎖定。任何時刻只能有一個任務取得該鎖。

這是一個協程。

release() None

釋放鎖。若有任何任務正在等待此鎖,則佇列中的下一個任務會被排程執行,且鎖維持鎖定狀態。否則,沒有任務在等待,鎖將變為未鎖定狀態。

TCP 串流連線

asyncio.open_connection(host: str, port: int, ssl: ssl.SSLContext | bool | None = None) Tuple[Stream, Stream]

開啟一個到給定 hostport 的 TCP 連線。host 位址將使用 socket.getaddrinfo() 解析,目前這是一個阻塞呼叫。若 ssl 是一個 ssl.SSLContext 物件,則會使用此情境來建立傳輸;若 sslTrue,則使用預設情境。

傳回一對串流:一個讀取器串流與一個寫入器串流。若無法解析主機或無法建立連線,將引發特定於通訊端的 OSError

這是一個協程。

asyncio.start_server(callback: Callable, host: str, port: int, backlog: int = 5, ssl: ssl.SSLContext | None = None) Server

在給定的 hostport 上啟動一個 TCP 伺服器。當有傳入並已接受的連線時,會呼叫 callback,並傳入 2 個引數:該連線的讀取器與寫入器串流。

ssl 是一個 ssl.SSLContext 物件,則會使用此情境來建立傳輸。

傳回一個 Server 物件。

這是一個協程。

class asyncio.Stream

此類別代表一個 TCP 串流連線。為了將程式碼最小化,此類別同時實作了讀取器與寫入器,且 StreamReaderStreamWriter 皆為此類別的別名。

get_extra_info(v: str) Any

取得關於串流的額外資訊,由 v 指定。v 的有效值為:peername

close() None

關閉串流。

wait_closed() None

等待串流關閉。

這是一個協程。

read(n: int = -1) bytes

讀取至多 n 個位元組並傳回它們。若未提供 n 或其值為 -1,則讀取所有位元組直到 EOF。若在讀取任何位元組前即遇到 EOF,則傳回值將是一個空的 bytes 物件。

這是一個協程。

readinto(buf: bytearray | memoryview) int

讀取至多 n 個位元組到 buf 中,n 等於 buf 的長度。

傳回讀取到 buf 中的位元組數。

這是一個協程,也是 MicroPython 的擴充功能。

readexactly(n: int) bytes

精確讀取 n 個位元組並以 bytes 物件傳回它們。

若串流在讀取 n 個位元組前即結束,則引發 EOFError 例外。

這是一個協程。

readline() bytes

讀取一行並傳回它。

這是一個協程。

write(buf: bytes) None

buf 累積到輸出緩衝區。資料僅在呼叫 Stream.drain() 時才會刷新。建議在呼叫此函式後立即呼叫 Stream.drain()

drain() None

將所有緩衝的輸出資料排空(寫出)到串流。

這是一個協程。

class asyncio.Server

此類別代表由 start_server() 傳回的伺服器類別。它可用於 async with 陳述式中,以便在離開時關閉伺服器。

close() None

關閉伺服器。

wait_closed() None

等待伺服器關閉。

這是一個協程。

事件迴圈

asyncio.get_event_loop() Loop

傳回用於排程與執行任務的事件迴圈。請參閱 Loop

asyncio.new_event_loop() Loop

重設事件迴圈並傳回它。

注意:由於 MicroPython 只有單一事件迴圈,因此此函式僅重設迴圈的狀態,並不會建立新的迴圈。

class asyncio.Loop

此類別代表負責排程與執行任務的物件。它無法被建立,請改用 get_event_loop()

create_task(coro: Coroutine) Task

從給定的 coro 建立一個任務並傳回新的 Task 物件。

run_forever() None

執行事件迴圈直到呼叫 stop()

run_until_complete(awaitable: Awaitable) Any

執行給定的 awaitable 直到它完成。若 awaitable 不是任務,則它會被提升為任務。

stop() None

停止事件迴圈。

close() None

關閉事件迴圈。

set_exception_handler(handler: Callable) None

設定當任務引發未被攔截的例外時要呼叫的例外處理常式。handler 應接受兩個引數:(loop, context)

get_exception_handler() Callable | None

取得目前的例外處理常式。傳回該處理常式,若未設定自訂處理常式則傳回 None

default_exception_handler(context: dict) None

被呼叫的預設例外處理常式。

call_exception_handler(context: dict) None

呼叫目前的例外處理常式。引數 context 會被傳遞,它是一個包含下列鍵的字典:'message''exception''future'