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'