事件循环¶
源代码: Lib/asyncio/events.py , Lib/asyncio/base_events.py
序言
事件循环是每个异步应用程序的核心。事件循环运行异步任务和回调,执行网络IO操作,并运行子进程。
应用程序开发人员通常应该使用高级异步函数,例如 asyncio.run()
并且很少需要引用循环对象或调用其方法。本节主要针对较低级别的代码、库和框架的作者,他们需要对事件循环行为进行更好的控制。
获取事件循环
以下低级函数可用于获取、设置或创建事件循环:
- asyncio.get_running_loop()¶
返回当前OS线程中正在运行的事件循环。
如果没有正在运行的事件循环A
RuntimeError
提高了。只能从协程或回调调用此函数。3.7 新版功能.
- asyncio.get_event_loop()¶
获取当前事件循环。
如果当前OS线程中没有设置当前事件循环,则OS线程是main,并且
set_event_loop()
尚未调用,Asyncio将创建一个新的事件循环,并将其设置为当前事件循环。因为此函数具有相当复杂的行为(特别是在使用自定义事件循环策略时),所以使用
get_running_loop()
功能优先于get_event_loop()
在协程和回调中。也可以考虑使用
asyncio.run()
函数,而不是使用较低级别的函数手动创建和关闭事件循环。
- asyncio.set_event_loop(loop)¶
集合 loop 作为当前OS线程的当前事件循环。
- asyncio.new_event_loop()¶
创建新的事件循环对象。
注意 get_event_loop()
, set_event_loop()
和 new_event_loop()
函数可以通过 setting a custom event loop policy .
目录
本文档页包含以下部分:
这个 Event Loop Methods 部分是事件循环API的参考文档;
这个 Callback Handles 章节文件
Handle
和TimerHandle
从调度方法返回的实例,如loop.call_soon()
和loop.call_later()
;这个 Server Objects 节文档从事件循环方法返回的类型,如
loop.create_server()
;这个 Event Loop Implementations 章节文件
SelectorEventLoop
和ProactorEventLoop
类;这个 Examples 部分展示了如何使用一些事件循环API。
事件循环方法¶
事件循环具有 low-level 以下应用程序接口:
运行和停止循环¶
- loop.run_until_complete(future)¶
运行直到 Future (实例)
Future
)已完成。如果参数是 coroutine object 它被隐式调度为作为
asyncio.Task
.返回未来的结果或引发异常。
- loop.run_forever()¶
运行事件循环直到
stop()
被称为。如果
stop()
以前调用过run_forever()
调用时,循环将轮询I/O选择器一次,超时为零,运行为响应I/O事件而计划的所有回调(以及已计划的回调),然后退出。如果
stop()
被称为run_forever()
正在运行,循环将运行当前批回调,然后退出。请注意,在这种情况下,由回调调度的新回调将不会运行;相反,它们将在下次运行run_forever()
或run_until_complete()
被称为。
- loop.stop()¶
停止事件循环。
- loop.is_running()¶
返回
True
如果事件循环当前正在运行。
- loop.is_closed()¶
返回
True
如果事件循环已关闭。
- loop.close()¶
关闭事件循环。
调用此函数时,循环不能运行。任何挂起的回调都将被丢弃。
此方法清除所有队列并关闭执行器,但不等待执行器完成。
这个方法是等幂的,不可逆的。关闭事件循环后,不应调用其他方法。
- coroutine loop.shutdown_asyncgens()¶
计划所有当前打开的 asynchronous generator 要关闭的对象
aclose()
调用。调用此方法后,如果迭代新的异步生成器,事件循环将发出警告。这应该用于可靠地完成所有预定的异步生成器。注意,当
asyncio.run()
使用。例子::
try: loop.run_forever() finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()
3.6 新版功能.
- coroutine loop.shutdown_default_executor()¶
调度默认执行器的关闭,并等待它加入
ThreadPoolExecutor
. 在调用此方法之后RuntimeError
如果loop.run_in_executor()
在使用默认执行器时调用。注意,当
asyncio.run()
使用。3.9 新版功能.
计划回调¶
- loop.call_soon(callback, *args, context=None)¶
安排 回调 callback 与…联系 args 事件循环的下一个迭代中的参数。
回调按注册顺序调用。每次回调都将被调用一次。
仅限可选关键字 context 参数允许指定自定义
contextvars.Context
对于 回调 运行进去。当否时使用当前上下文 context 提供。的实例
asyncio.Handle
返回,稍后可用于取消回调。此方法不是线程安全的。
- loop.call_soon_threadsafe(callback, *args, context=None)¶
线程安全变体
call_soon()
. 必须用于计划回调 从另一条线 .见 concurrency and multithreading 文档的节。
在 3.7 版更改: 这个 context 只添加关键字参数。见 PEP 567 了解更多详细信息。
注解
大多数 asyncio
调度函数不允许传递关键字参数。为此,请使用 functools.partial()
::
# will schedule "print("Hello", flush=True)"
loop.call_soon(
functools.partial(print, "Hello", flush=True))
使用分部对象通常比使用lambda更方便,因为Asyncio可以在调试和错误消息中更好地呈现分部对象。
计划延迟回调¶
事件循环提供了一些机制来安排在将来某个时候调用回调函数。事件循环使用单调的时钟来跟踪时间。
- loop.call_later(delay, callback, *args, context=None)¶
地铁列车时刻表 回调 在给定的 延迟 秒数(可以是int或float)。
的实例
asyncio.TimerHandle
返回,可用于取消回调。回调 将被调用一次。如果两次回调的调度时间完全相同,则调用它们的顺序是未定义的。
可选位置 args 将在调用回调时传递给回调。如果要使用关键字参数调用回调,请使用
functools.partial()
.仅限可选关键字 context 参数允许指定自定义
contextvars.Context
对于 回调 运行进去。当否时使用当前上下文 context 提供。在 3.7 版更改: 这个 context 只添加关键字参数。见 PEP 567 了解更多详细信息。
在 3.8 版更改: 在Python3.7及更早版本中,使用默认的事件循环实现, 延迟 不能超过一天。这已经在Python3.8中修复。
- loop.call_at(when, callback, *args, context=None)¶
地铁列车时刻表 回调 在给定的绝对时间戳处调用 when (int或float),使用与
loop.time()
.此方法的行为与
call_later()
.的实例
asyncio.TimerHandle
返回,可用于取消回调。在 3.7 版更改: 这个 context 只添加关键字参数。见 PEP 567 了解更多详细信息。
在 3.8 版更改: 在Python3.7和早期的缺省事件循环实现中, when 当前时间不能超过一天。这已经在Python3.8中修复。
注解
在 3.8 版更改: 在python 3.7和更早的超时中(相对 延迟 或绝对 when )不应超过一天。这已经在Python3.8中修复。
参见
这个 asyncio.sleep()
功能。
创造未来和任务¶
- loop.create_future()¶
创建一个
asyncio.Future
附加到事件循环的对象。这是在Asyncio中创建期货的首选方法。这允许第三方事件循环提供未来对象的替代实现(具有更好的性能或工具)。
3.5.2 新版功能.
- loop.create_task(coro, *, name=None)¶
-
第三方事件循环可以使用自己的子类
Task
为了互操作性。在这种情况下,结果类型是Task
.如果 name 是否提供参数
None
,它设置为任务的名称,使用Task.set_name()
.在 3.8 版更改: 增加了
name
参数。
- loop.set_task_factory(factory)¶
设置将由使用的任务工厂
loop.create_task()
.如果 工厂 是
None
将设置默认的任务工厂。否则, 工厂 必须是 可赎回的 与签名匹配(loop, coro)
在哪里 loop 是对活动事件循环的引用,并且 coro 是协程对象。可调用文件必须返回asyncio.Future
-兼容对象。
- loop.get_task_factory()¶
返回任务工厂或
None
如果使用默认值。
打开网络连接¶
- coroutine loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None)¶
打开到由指定的给定地址的流传输连接 host 和 port .
Socket系列可以是
AF_INET
或AF_INET6
取决于 host (或 家庭 参数(如果提供)。Socket类型为
SOCK_STREAM
.protocol_factory 必须是可调用的返回 asyncio protocol 实施。
此方法将尝试在后台建立连接。成功后,它返回
(transport, protocol)
一对。底层操作的时间概要如下:
连接已建立,并且 transport 是为它创建的。
protocol_factory 调用时不带参数,应返回 protocol 实例。
协议实例通过调用其
connection_made()
方法。A
(transport, protocol)
成功时返回元组。
创建的传输是依赖于实现的双向流。
其他参数:
ssl :如果给定且不为假,则创建SSL/TLS传输(默认情况下,创建纯TCP传输)。如果 ssl 是一个
ssl.SSLContext
对象,此上下文用于创建传输;如果 ssl 是True
,从返回的默认上下文ssl.create_default_context()
使用。server_hostname 设置或重写目标服务器证书将与之匹配的主机名。只有在 ssl 不是
None
.默认情况下 host 使用了参数。如果 host 为空,没有默认值,必须传递 server_hostname . 如果 server_hostname 是一个空字符串,主机名匹配被禁用(这是一个严重的安全风险,允许潜在的中间人攻击)。家庭 , 原始的 , flags 是要传递给getaddrinfo()的可选地址系列、协议和标志吗? host 分辨率。如果给定,这些应该都是对应的
socket
模块常量。happy_eyeballs_delay 如果提供,则可以为该连接启用快乐眼球。它应该是一个浮点数,表示在开始下一次并行尝试之前等待连接尝试完成的时间(以秒为单位)。这是中定义的“连接尝试延迟” RFC 8305 . RFC建议的合理默认值是
0.25
(250毫秒)。交错 控制主机名解析为多个IP地址时的地址重新排序。如果
0
或未指定,未进行重新排序,地址将按返回的顺序尝试getaddrinfo()
. 如果指定了正整数,则地址由地址族交错,并且给定的整数被解释为“第一个地址族计数”,如中所定义。 RFC 8305 . 默认值为0
如果 happy_eyeballs_delay 未指定,并且1
如果是的话。sock 如果给定,则应为已连接的现有
socket.socket
要由传输使用的对象。如果 sock 被给予,没有 host , port , 家庭 , 原始的 , 旗帜 , happy_eyeballs_delay , 交错 和 local_addr 应指定。local_addr 如果给出,则为
(local_host, local_port)
用于将套接字绑定到本地的元组。这个 local_host 和 local_port 使用查找getaddrinfo()
类似于 host 和 port .ssl_handshake_timeout 是(对于TLS连接)在中止连接之前等待TLS握手完成的时间(秒)。
60.0
秒,如果None
(默认)。
3.8 新版功能: 增加了 happy_eyeballs_delay 和 交错 参数。
快乐眼球算法:双栈主机的成功。当服务器的IPv4路径和协议工作,但服务器的IPv6路径和协议不工作时,与仅使用IPv4的客户端相比,双堆栈客户端应用程序会经历显著的连接延迟。这是不可取的,因为它会导致双堆栈客户机具有更差的用户体验。本文件规定了减少用户可见延迟的算法要求,并提供了算法。
3.7 新版功能: 这个 ssl_handshake_timeout 参数。
在 3.6 版更改: Socket选项
TCP_NODELAY
默认情况下为所有TCP连接设置。在 3.5 版更改: 在中添加了对SSL/TLS的支持
ProactorEventLoop
.参见
这个
open_connection()
函数是一个高级的可选API。它返回一对 (StreamReader
,StreamWriter
)可以直接在异步/等待代码中使用。
- coroutine loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None)¶
注解
参数 reuse_address 不再支持,因为使用
SO_REUSEADDR
对UDP提出了一个重要的安全问题。显式传递reuse_address=True
将引发异常。当具有不同uid的多个进程将套接字分配给具有
SO_REUSEADDR
,传入的数据包可以在套接字之间随机分布。对于支持的平台, reuse_port 可作为类似功能的替代品。与 reuse_port ,
SO_REUSEPORT
相反,它特别防止具有不同uid的进程将套接字分配给同一个套接字地址。创建数据报连接。
Socket系列可以是
AF_INET
,AF_INET6
或AF_UNIX
取决于 host (或 家庭 参数(如果提供)。Socket类型为
SOCK_DGRAM
.protocol_factory 必须是可调用的返回 protocol 实施。
一个元组
(transport, protocol)
成功时返回。其他参数:
local_addr 如果给出,则为
(local_host, local_port)
用于将套接字绑定到本地的元组。这个 local_host 和 local_port 使用查找getaddrinfo()
.remote_addr 如果给出,则为
(remote_host, remote_port)
用于将套接字连接到远程地址的元组。这个 remote_host 和 remote_port 使用查找getaddrinfo()
.家庭 , 原始的 , flags 要传递到的可选地址系列、协议和标志
getaddrinfo()
对于 host 分辨率。如果给定,这些应该都是对应的socket
模块常量。reuse_port 告诉内核允许此端点绑定到与其他现有端点绑定到的端口相同的端口,只要它们在创建时都设置了此标志。Windows和某些Unix不支持此选项。如果
SO_REUSEPORT
未定义常量,则不支持此功能。allow_broadcast 告诉内核允许此端点向广播地址发送消息。
sock 可以选择指定,以便使用先前存在的、已连接的,
socket.socket
要由传输使用的对象。如果指定, local_addr 和 remote_addr 应省略(必须None
)
见 UDP echo client protocol 和 UDP echo server protocol 示例。
在 3.4.4 版更改: 这个 家庭 , 原始的 , flags , reuse_address , reuse_port, * allow_broadcast *和 已添加sock*参数。
在 3.8.1 版更改: 这个 reuse_address 由于安全问题,不再支持参数。
在 3.8 版更改: 添加了对Windows的支持。
- coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None)¶
创建一个Unix连接。
Socket系列将
AF_UNIX
;Socket类型为SOCK_STREAM
.一个元组
(transport, protocol)
成功时返回。path 是Unix域套接字的名称,并且是必需的,除非 sock 指定了参数。抽象Unix套接字,
str
,bytes
和Path
支持路径。参见
loop.create_connection()
方法获取有关此方法的参数的信息。Availability UNIX。
3.7 新版功能: 这个 ssl_handshake_timeout 参数。
在 3.7 版更改: 这个 path 参数现在可以是 path-like object .
创建网络服务器¶
- coroutine loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)¶
创建TCP服务器(套接字类型
SOCK_STREAM
听 port 的 host 地址。返回A
Server
对象。参数:
protocol_factory 必须是可调用的返回 protocol 实施。
这个 host 可以将参数设置为若干类型,这些类型决定服务器将在何处侦听:
如果 host 是字符串,TCP服务器绑定到由指定的单个网络接口 host .
如果 host 是字符串序列,TCP服务器绑定到该序列指定的所有网络接口。
如果 host 是空字符串或
None
,将假定所有接口,并返回多个套接字的列表(很可能一个用于IPv4,另一个用于IPv6)。
家庭 可以设置为
socket.AF_INET
或AF_INET6
强制套接字使用IPv4或IPv6。如果没有设置, 家庭 将由主机名确定(默认为AF_UNSPEC
)flags 是位掩码
getaddrinfo()
.sock 可以选择指定以使用先前存在的套接字对象。如果指定, host 和 port 不能指定。
积压 是传递到的排队连接的最大数目
listen()
(默认为100)。ssl 可以设置为
SSLContext
实例以在接受的连接上启用TLS。reuse_address 告诉内核在
TIME_WAIT
状态,而不等待其自然超时到期。如果未指定,将自动设置为True
在UNIX上。reuse_port 告诉内核允许此端点绑定到与其他现有端点绑定到的端口相同的端口,只要它们在创建时都设置了此标志。Windows不支持此选项。
ssl_handshake_timeout 是(对于TLS服务器)在中止连接之前等待TLS握手完成的时间(秒)。
60.0
秒,如果None
(默认)。start_serving 设置为
True
(默认)使创建的服务器立即开始接受连接。当设置为False
,用户应等待Server.start_serving()
或Server.serve_forever()
使服务器开始接受连接。
3.7 新版功能: 补充 ssl_handshake_timeout 和 start_serving 参数。
在 3.6 版更改: Socket选项
TCP_NODELAY
默认情况下为所有TCP连接设置。在 3.5 版更改: 在中添加了对SSL/TLS的支持
ProactorEventLoop
.在 3.5.1 版更改: 这个 host 参数可以是字符串序列。
参见
这个
start_server()
函数是返回一对StreamReader
和StreamWriter
可以在异步/等待代码中使用。
- coroutine loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)¶
类似
loop.create_server()
但与AF_UNIX
套接字族。path 是Unix域套接字的名称,并且是必需的,除非 sock 提供了参数。抽象Unix套接字,
str
,bytes
和Path
支持路径。参见
loop.create_server()
方法获取有关此方法的参数的信息。Availability UNIX。
3.7 新版功能: 这个 ssl_handshake_timeout 和 start_serving 参数。
在 3.7 版更改: 这个 path 参数现在可以是
Path
对象。
- coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None)¶
将已接受的连接封装到传输/协议对中。
此方法可由接受Asyncio之外的连接但使用Asyncio处理这些连接的服务器使用。
参数:
protocol_factory 必须是可调用的返回 protocol 实施。
sock 是从返回的先前存在的套接字对象
socket.accept
.ssl 可以设置为
SSLContext
在接受的连接上启用SSL。ssl_handshake_timeout 是(对于SSL连接)在中止连接之前等待SSL握手完成的时间(秒)。
60.0
秒,如果None
(默认)。
返回A
(transport, protocol)
一对。3.7 新版功能: 这个 ssl_handshake_timeout 参数。
3.5.3 新版功能.
传输文件¶
- coroutine loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)¶
发送一个 file 过了*transport*. 返回发送的字节总数。
该方法使用高性能
os.sendfile()
如果有的话。file 必须是以二进制模式打开的常规文件对象。
抵消 告诉从何处开始读取文件。如果指定, 计数 是要传输的总字节数,而不是在达到EOF之前发送文件。即使此方法引发错误,也始终更新文件位置,并且
file.tell()
可用于获取实际发送的字节数。fallback 设置为
True
使asyncio在平台不支持send file系统调用(例如,UNIX上的Windows或SSL套接字)时手动读取和发送文件。提高
SendfileNotAvailableError
如果系统不支持 发送文件 系统调用和 fallback 是False
.3.7 新版功能.
TLS升级¶
- coroutine loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None)¶
将现有的基于传输的连接升级到TLS。
返回一个新的传输实例, 协议 必须立即开始使用 等待 . 这个*transport*实例传递到 start_tls 方法不应再使用。
参数:
传输 和 协议 方法类似于的实例
create_server()
和create_connection()
返回。SSLcontext :的已配置实例
SSLContext
.server_side 通过
True
当服务器端连接正在升级时(如由create_server()
)server_hostname :设置或重写目标服务器证书将与之匹配的主机名。
ssl_handshake_timeout 是(对于TLS连接)在中止连接之前等待TLS握手完成的时间(秒)。
60.0
秒,如果None
(默认)。
3.7 新版功能.
监视文件描述符¶
- loop.add_reader(fd, callback, *args)¶
开始监视 fd 用于读取可用性和调用的文件描述符 回调 使用指定的参数一次 fd 可供阅读。
- loop.remove_reader(fd)¶
停止监视 fd 用于读取可用性的文件描述符。
- loop.add_writer(fd, callback, *args)¶
开始监视 fd 用于写入可用性和调用的文件描述符 回调 使用指定的参数一次 fd 可用于书写。
使用
functools.partial()
to pass keyword arguments 到 回调 .
- loop.remove_writer(fd)¶
停止监视 fd 用于写入可用性的文件描述符。
也见 Platform Support 有关这些方法的某些限制的部分。
直接使用套接字对象¶
通常,使用基于传输的API的协议实现,例如 loop.create_connection()
和 loop.create_server()
比直接使用套接字的实现更快。但是,当性能不是关键的,并且使用 socket
对象直接更方便。
- coroutine loop.sock_recv(sock, nbytes)¶
接收到 字节数 从 sock . 的异步版本
socket.recv()
.以字节对象的形式返回接收到的数据。
sock 必须是非阻塞套接字。
在 3.7 版更改: 尽管这个方法总是被记录为协程方法,但在Python3.7之前的版本返回了
Future
.因为python 3.7,这是一个async def
方法。
- coroutine loop.sock_recv_into(sock, buf)¶
从接收数据 sock 进入 buf 缓冲器。根据阻塞建模
socket.recv_into()
方法。返回写入缓冲区的字节数。
sock 必须是非阻塞套接字。
3.7 新版功能.
- coroutine loop.sock_sendall(sock, data)¶
发送 data 到 sock Socket。的异步版本
socket.sendall()
.此方法继续发送到套接字,直到 data 已发送或发生错误。
None
成功时返回。出错时引发异常。此外,无法确定连接的接收端成功处理了多少数据(如果有)。sock 必须是非阻塞套接字。
在 3.7 版更改: 尽管该方法始终被记录为协程方法,但在Python3.7之前,它返回了
Future
. 从python 3.7开始,这是一个async def
方法。
- coroutine loop.sock_connect(sock, address)¶
连接 sock 到远程Socket 地址 .
的异步版本
socket.connect()
.sock 必须是非阻塞套接字。
在 3.5.2 版更改:
address
不再需要解决。sock_connect
将尝试检查 地址 已通过调用解决socket.inet_pton()
. 如果不是,loop.getaddrinfo()
将用于解决 地址 .
- coroutine loop.sock_accept(sock)¶
接受连接。根据阻塞建模
socket.accept()
方法。套接字必须绑定到地址并侦听连接。返回值是一对
(conn, address)
在哪里? conn 是一个 new 可用于在连接上发送和接收数据的套接字对象,以及 地址 是绑定到连接另一端套接字的地址。sock 必须是非阻塞套接字。
在 3.7 版更改: 尽管该方法始终被记录为协程方法,但在Python3.7之前,它返回了
Future
. 从python 3.7开始,这是一个async def
方法。
- coroutine loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)¶
使用高性能发送文件
os.sendfile
如果可能的话。返回发送的字节总数。的异步版本
socket.sendfile()
.sock 必须是非阻塞的
socket.SOCK_STREAM
socket
.file 必须是以二进制模式打开的常规文件对象。
抵消 告诉从何处开始读取文件。如果指定, 计数 是要传输的总字节数,而不是在达到EOF之前发送文件。即使此方法引发错误,也始终更新文件位置,并且
file.tell()
可用于获取实际发送的字节数。fallback ,当设置为
True
,使Asyncio在平台不支持send file syscall(例如,UNIX上的Windows或SSL套接字)时手动读取和发送文件。提高
SendfileNotAvailableError
如果系统不支持 发送文件 系统调用和 fallback 是False
.sock 必须是非阻塞套接字。
3.7 新版功能.
DNS¶
- coroutine loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)¶
的异步版本
socket.getaddrinfo()
.
- coroutine loop.getnameinfo(sockaddr, flags=0)¶
的异步版本
socket.getnameinfo()
.
在 3.7 版更改: 两个 获取信息 和 GETNAMEFIN信息 方法总是被记录为返回协同程序,但在Python3.7之前,它们实际上是返回的 asyncio.Future
物体。从Python3.7开始,这两种方法都是协同程序。
使用管道¶
- coroutine loop.connect_read_pipe(protocol_factory, pipe)¶
注册的读取结束 pipe 在事件循环中。
protocol_factory 必须是可调用的返回 asyncio protocol 实施。
pipe 是一个 file-like object .
返回对
(transport, protocol)
在哪里*transport*支持ReadTransport
界面与 协议 是由 protocol_factory .用
SelectorEventLoop
事件循环 pipe 设置为非阻塞模式。
- coroutine loop.connect_write_pipe(protocol_factory, pipe)¶
注册的写入结束 pipe 在事件循环中。
protocol_factory 必须是可调用的返回 asyncio protocol 实施。
pipe 是 file-like object .
返回对
(transport, protocol)
在哪里*transport*支架WriteTransport
界面与 协议 是由 protocol_factory .用
SelectorEventLoop
事件循环 pipe 设置为非阻塞模式。
注解
SelectorEventLoop
在Windows上不支持上述方法。使用 ProactorEventLoop
而不是Windows。
参见
Unix信号¶
- loop.add_signal_handler(signum, callback, *args)¶
集合 回调 作为 symbol 信号。
回调将由调用 loop 以及该事件循环的其他排队回调和可运行协程。与使用注册的信号处理程序不同
signal.signal()
,允许用此函数注册的回调与事件循环交互。提高
ValueError
如果信号号无效或无法识别。提高RuntimeError
如果设置处理程序时出现问题。使用
functools.partial()
to pass keyword arguments 到 回调 .类似于
signal.signal()
,必须在主线程中调用此函数。
- loop.remove_signal_handler(sig)¶
删除的处理程序 sig 信号。
返回
True
如果信号处理程序被删除,或False
如果没有为给定的信号设置处理程序。Availability UNIX。
参见
这个 signal
模块。
在线程或进程池中执行代码¶
- awaitable loop.run_in_executor(executor, func, *args)¶
安排 func 在指定的执行器中被调用。
这个 遗嘱执行人 参数应为
concurrent.futures.Executor
实例。如果 遗嘱执行人 是None
.例子::
import asyncio import concurrent.futures def blocking_io(): # File operations (such as logging) can block the # event loop: run them in a thread pool. with open('/dev/urandom', 'rb') as f: return f.read(100) def cpu_bound(): # CPU-bound operations will block the event loop: # in general it is preferable to run them in a # process pool. return sum(i * i for i in range(10 ** 7)) async def main(): loop = asyncio.get_running_loop() ## Options: # 1. Run in the default loop's executor: result = await loop.run_in_executor( None, blocking_io) print('default thread pool', result) # 2. Run in a custom thread pool: with concurrent.futures.ThreadPoolExecutor() as pool: result = await loop.run_in_executor( pool, blocking_io) print('custom thread pool', result) # 3. Run in a custom process pool: with concurrent.futures.ProcessPoolExecutor() as pool: result = await loop.run_in_executor( pool, cpu_bound) print('custom process pool', result) asyncio.run(main())
此方法返回
asyncio.Future
对象。使用
functools.partial()
to pass keyword arguments 到 func .在 3.5.3 版更改:
loop.run_in_executor()
不再配置max_workers
它创建的线程池执行器,而不是将其留给线程池执行器 (ThreadPoolExecutor
)设置默认值。
- loop.set_default_executor(executor)¶
集合 遗嘱执行人 作为默认的执行者
run_in_executor()
. 遗嘱执行人 应该是ThreadPoolExecutor
.3.8 版后已移除: 使用的执行器不是
ThreadPoolExecutor
已弃用,将在python 3.9中触发错误。遗嘱执行人 必须是的实例
concurrent.futures.ThreadPoolExecutor
.
错误处理API¶
允许自定义如何在事件循环中处理异常。
- loop.set_exception_handler(handler)¶
集合 处理程序 作为新的事件循环异常处理程序。
如果 处理程序 是
None
将设置默认的异常处理程序。否则, 处理程序 必须是签名匹配的可调用(loop, context)
在哪里loop
是对活动事件循环的引用,并且context
是一个dict
包含异常详细信息的对象(请参见call_exception_handler()
有关上下文的详细信息的文档)。
- loop.get_exception_handler()¶
返回当前异常处理程序,或者
None
如果未设置自定义异常处理程序。3.5.2 新版功能.
- loop.default_exception_handler(context)¶
默认异常处理程序。
当发生异常且未设置异常处理程序时,将调用此函数。这可以由想要遵从默认处理程序行为的自定义异常处理程序调用。
context 参数的含义与中的相同
call_exception_handler()
.
- loop.call_exception_handler(context)¶
调用当前事件循环异常处理程序。
context 是一个
dict
包含以下键的对象(在将来的Python版本中可能会引入新键):“message”:错误消息;
“exception”(可选):exception对象;
“未来”(可选):
asyncio.Future
实例;‘Task’(可选):
asyncio.Task
实例;“手柄”(可选):
asyncio.Handle
实例;“协议”(可选): Protocol 实例;
“传输”(可选): Transport 实例;
‘socket’(可选):
socket.socket
实例;- “asyncgen”(可选):导致
例外情况。
注解
不应在子类事件循环中重载此方法。对于自定义异常处理,请使用
set_exception_handler()
方法。
启用调试模式¶
- loop.get_debug()¶
获取调试模式 (
bool
)事件循环的。默认值为
True
如果环境变量PYTHONASYNCIODEBUG
设置为非空字符串,False
否则。
- loop.set_debug(enabled: bool)¶
设置事件循环的调试模式。
在 3.7 版更改: 新的 Python Development Mode 现在也可以用于启用调试模式。
参见
正在运行子流程¶
本小节中描述的方法是低级的。在常规异步/等待代码中,考虑使用高级 asyncio.create_subprocess_shell()
和 asyncio.create_subprocess_exec()
便利功能取而代之。
注解
默认的异步事件循环 Windows 不支持子进程。见 Subprocess Support on Windows 有关详细信息。
- coroutine loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶
从由指定的一个或多个字符串参数创建子进程 args .
args 必须是字符串列表,由以下内容表示:
str
;或
bytes
,编码到 filesystem encoding .
第一个字符串指定程序可执行文件,其余字符串指定参数。字符串参数一起构成
argv
的程序。这类似于标准库
subprocess.Popen
用调用的类shell=False
以及作为第一个参数传递的字符串列表;但是,其中Popen
采用字符串列表的单个参数, subprocess_exec 采用多个字符串参数。这个 protocol_factory 必须是可调用的,返回
asyncio.SubprocessProtocol
类。其他参数:
斯坦丁 可以是以下任何一种:
表示要连接到子进程标准输入流的管道的类似文件的对象,使用
connect_write_pipe()
这个
subprocess.PIPE
常量(默认值),它将创建一个新管道并将其连接,价值
None
这将使子进程从此进程继承文件描述符这个
subprocess.DEVNULL
常数,表示os.devnull
将使用文件
标准输出 可以是以下任何一种:
表示要连接到子进程标准输出流的管道的类似文件的对象,使用
connect_write_pipe()
这个
subprocess.PIPE
常量(默认值),它将创建一个新管道并将其连接,价值
None
这将使子进程从此进程继承文件描述符这个
subprocess.DEVNULL
常数,表示os.devnull
将使用文件
标准错误 可以是以下任何一种:
表示要连接到子进程标准错误流的管道的类似文件的对象,使用
connect_write_pipe()
这个
subprocess.PIPE
常量(默认值),它将创建一个新管道并将其连接,价值
None
这将使子进程从此进程继承文件描述符这个
subprocess.DEVNULL
常数,表示os.devnull
将使用文件这个
subprocess.STDOUT
将标准错误流连接到进程的标准输出流的常量
所有其他关键字参数都传递给
subprocess.Popen
无解释,除非 蟾蜍尺码 , universal_newlines , 壳 , text , 编码 和 错误 ,完全不应指定。这个
asyncio
子进程API不支持将流解码为文本。bytes.decode()
可用于将流返回的字节转换为文本。
请参见
subprocess.Popen
用于其他参数的文档的类。返回一对
(transport, protocol)
在哪里*transport*符合asyncio.SubprocessTransport
基类和 协议 是由 protocol_factory .
- coroutine loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶
从创建子流程 cmd ,可以是
str
或Abytes
字符串编码到 filesystem encoding ,使用平台的“shell”语法。这类似于标准库
subprocess.Popen
用调用的类shell=True
.这个 protocol_factory 必须是可调用的,返回
SubprocessProtocol
类。见
subprocess_exec()
有关其余参数的详细信息。返回一对
(transport, protocol)
在哪里*transport*符合SubprocessTransport
基类和 协议 是由 protocol_factory .
注解
应用程序有责任确保所有空格和特殊字符都被适当地引用,以避免 shell injection 漏洞。这个 shlex.quote()
函数可用于正确转义将用于构造shell命令的字符串中的空白和特殊字符。
回调句柄¶
- class asyncio.Handle¶
由返回的回调封装器对象
loop.call_soon()
,loop.call_soon_threadsafe()
.- cancel()¶
取消回拨。如果回调已被取消或执行,则此方法无效。
- cancelled()¶
返回
True
如果取消了回调。3.7 新版功能.
- class asyncio.TimerHandle¶
由返回的回调封装器对象
loop.call_later()
和loop.call_at()
.这个类是
Handle
.- when()¶
将计划的回调时间返回为
float
秒。时间是一个绝对时间戳,使用与
loop.time()
.3.7 新版功能.
服务器对象¶
服务器对象由创建 loop.create_server()
, loop.create_unix_server()
, start_server()
和 start_unix_server()
功能。
不要直接实例化类。
- class asyncio.Server¶
服务器 对象是异步上下文管理器。当用于
async with
语句,它保证服务器对象已关闭,并且在async with
语句已完成::srv = await loop.create_server(...) async with srv: # some code # At this point, srv is closed and no longer accepts new connections.
在 3.7 版更改: 服务器对象是自Python3.7以来的异步上下文管理器。
- close()¶
停止服务:关闭监听Socket并设置
sockets
属性到None
.表示现有传入客户端连接的套接字保持打开状态。
服务器异步关闭,请使用
wait_closed()
协程等待服务器关闭。
- get_loop()¶
返回与服务器对象关联的事件循环。
3.7 新版功能.
- coroutine start_serving()¶
开始接受连接。
此方法是等幂的,因此当服务器已经在服务时可以调用它。
这个 start_serving 仅关键字参数到
loop.create_server()
和asyncio.start_server()
允许创建最初不接受连接的服务器对象。在这种情况下Server.start_serving()
或Server.serve_forever()
可用于使服务器开始接受连接。3.7 新版功能.
- coroutine serve_forever()¶
开始接受连接,直到协程被取消。取消
serve_forever
任务导致服务器关闭。如果服务器已接受连接,则可以调用此方法。只有一个
serve_forever
每个任务可以存在 服务器 对象。例子::
async def client_connected(reader, writer): # Communicate with the client with # reader/writer streams. For example: await reader.readline() async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) await srv.serve_forever() asyncio.run(main('127.0.0.1', 0))
3.7 新版功能.
- is_serving()¶
返回
True
如果服务器正在接受新连接。3.7 新版功能.
- sockets¶
名单
socket.socket
服务器正在侦听的对象。在 3.7 版更改: 在python 3.7之前
Server.sockets
用于直接返回服务器套接字的内部列表。在3.7中,返回该列表的副本。
事件循环实现¶
异步与两种不同的事件循环实现: SelectorEventLoop
和 ProactorEventLoop
.
默认情况下,Asyncio配置为使用 SelectorEventLoop
在UNIX上 ProactorEventLoop
在Windows上。
- class asyncio.SelectorEventLoop¶
基于
selectors
模块。使用最有效的 selectors 可用于给定平台。还可以手动配置要使用的确切选择器实现:
import asyncio import selectors selector = selectors.SelectSelector() loop = asyncio.SelectorEventLoop(selector) asyncio.set_event_loop(loop)
Availability :Unix、Windows。
- class asyncio.ProactorEventLoop¶
使用“I/O完成端口”(IOCP)的Windows事件循环。
Availability :Windows。
参见
MSDN documentation on I/O Completion Ports <https://docs.microsoft.com/en-ca/windows/desktop/FileIO/i-o-completion-ports> _.
- class asyncio.AbstractEventLoop¶
异步兼容事件循环的抽象基类。
这个 Event Loop Methods 第节列出了
AbstractEventLoop
应该已经定义了。
实例¶
注意本节中的所有示例 有目的地 演示如何使用低级事件循环API,例如 loop.run_forever()
和 loop.call_soon()
. 现代异步应用程序很少需要这样编写;考虑使用高级函数,如 asyncio.run()
.
你好,有调用的世界¶
使用的示例 loop.call_soon()
方法来安排回调。回调显示 "Hello World"
然后停止事件循环:
import asyncio
def hello_world(loop):
"""A callback to print 'Hello World' and stop the event loop"""
print('Hello World')
loop.stop()
loop = asyncio.get_event_loop()
# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
参见
类似的 Hello World 使用协程和 run()
功能。
使用call_later()显示当前日期¶
每秒显示当前日期的回调示例。回调使用 loop.call_later()
方法在5秒后重新计划自身,然后停止事件循环:
import asyncio
import datetime
def display_date(end_time, loop):
print(datetime.datetime.now())
if (loop.time() + 1.0) < end_time:
loop.call_later(1, display_date, end_time, loop)
else:
loop.stop()
loop = asyncio.get_event_loop()
# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
参见
类似的 current date 使用协程和 run()
功能。
监视文件描述符的读取事件¶
等待,直到文件描述符接收到使用 loop.add_reader()
方法,然后关闭事件循环:
import asyncio
from socket import socketpair
# Create a pair of connected file descriptors
rsock, wsock = socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# We are done: unregister the file descriptor
loop.remove_reader(rsock)
# Stop the event loop
loop.stop()
# Register the file descriptor for read event
loop.add_reader(rsock, reader)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
try:
# Run the event loop
loop.run_forever()
finally:
# We are done. Close sockets and the event loop.
rsock.close()
wsock.close()
loop.close()
参见
类似的 example 使用传输、协议和
loop.create_connection()
方法。另一相似 example 使用高级
asyncio.open_connection()
函数和流。
为sigint和sigterm设置信号处理程序¶
(这个 signals
示例仅适用于UNIX。)
为信号注册处理程序 SIGINT
和 SIGTERM
使用 loop.add_signal_handler()
方法:
import asyncio
import functools
import os
import signal
def ask_exit(signame, loop):
print("got signal %s: exit" % signame)
loop.stop()
async def main():
loop = asyncio.get_running_loop()
for signame in {'SIGINT', 'SIGTERM'}:
loop.add_signal_handler(
getattr(signal, signame),
functools.partial(ask_exit, signame, loop))
await asyncio.sleep(3600)
print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")
asyncio.run(main())