事件循环 – 异步I / O(Python教程)(参考资料)
事件循环
前言
事件循环是每个asyncio应用程序的核心。事件循环运行异步任务和回调,执行networkIO操作,并运行子进程.
应用程序开发人员通常应该使用高级asyncio函数,例如asyncio.run()
,并且很少需要引用loopobject或调用其方法。本节主要面向低级代码,库和框架的作者,他们需要更好地控制事件循环行为.
获取事件循环
以下低级函数可用于获取,设置或创建事件循环:
asyncio.
get_event_loop
()-
获取当前事件循环。如果当前操作系统线程中没有设置当前事件循环并且
set_event_loop()
尚未调用,则asyncio将创建一个新的事件循环并将其设置为当前操作系统.因为这个函数有相当复杂的行为(尤其是在使用自定义事件循环策略时),使用
get_running_loop()
函数优于get_event_loop()
在coroutines和callbacks.考虑使用
asyncio.run()
函数而不是使用较低级别的函数来手动创建和关闭事件循环.
asyncio.
set_event_loop
(loop)-
/loop作为当前OS线程的当前事件循环.
asyncio.
new_event_loop
()-
创建一个新的事件循环对象.
注意get_event_loop()
, set_event_loop()
,和new_event_loop()
功能可以改变设置自定义事件循环策略.
内容
本文档页面包含以下部分:
- 事件循环方法部分是事件循环API的参考文档;
- 回调句柄部分记录了
Handle
和TimerHandle
实例,这些实例是从调度方法返回的,例如loop.call_soon()
和loop.call_later()
; - 服务器对象部分文档类型返回fromevent循环方法,如
loop.create_server()
; - 事件循环实现部分记录了
SelectorEventLoop
和ProactorEventLoop
类; - 示例部分展示了如何使用一些eventloop API .
事件循环方法
事件循环有低级 API用于以下内容:
运行和停止循环
loop.
run_until_complete
(future)-
运行到future(
Future
的一个例子)已完成如果论证是协程对象itis隐式计划以
asyncio.Task
.运行返回Future的结果或提高它的异常.
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
() -
计划当前打开异步发生器物品与
aclose()
呼叫。调用此方法后,如果迭代了新的异步生成器,则事件循环将发出警告。这应该用于可靠地完成所有预定的同步发电机.请注意,
asyncio.run()
用来。例:
try: loop.run_forever()finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()
版本3.6.
调度回调
loop.
call_soon
(callback, *args, context=None)-
安排一个 callback跟打电话args在事件循环的下一次迭代中的参数
//按照它们的注册顺序调用。每次回调都会被调用一次.
一个可选的关键字context参数允许指定自定义
contextvars.Context
为了 callback运行。当没有context提供了的一个例子
asyncio.Handle
返回,以后可以用来取消回调.这种方法不是线程安全的
loop.
call_soon_threadsafe
(callback, *args, context=None)-
的线程安全变体
call_soon()
。必须使用toschedule回调from another thread.见并发和多线程文档部分.
更改版本3.7:添加了context keyword-only参数。见 PEP 567 了解更多详情.
调度延迟回调
事件循环提供了调度回调函数的机制,以便在将来的某个时刻调用。事件循环使用monotonicclocks跟踪时间
loop.
call_later
(delay, callback, *args, context=None )-
计划callback在给定的delay秒数之后调用(可以是int或float).
返回
asyncio.TimerHandle
的实例,可以用来取消回调.callback将被称为恰好一次。如果两个回调计划的时间完全相同,那么它们的调用顺序是不确定的.
可选的位置args将在调用时传递给回调函数。如果你想用关键字参数调用回调,请使用
functools.partial()
.一个可选的关键字context参数允许指定acustom
contextvars.Context
为了callback来运行。当没有提供context时使用当前的上下文.在版本3.7中改变: context添加了仅限关键字的参数。见 PEP 567 有关详细信息.
更改版本3.7.1:在Python 3.7.0及更早版本中使用默认事件循环实现,delay不能超过一天。这已在Python 3.7.1.
loop.
call_at
(when, callback, *args, context=None)-
安排callback在给定的绝对时间戳上调用when(一个int或一个浮点数),使用与
loop.time()
.相同的时间引用。此方法的行为与
call_later()
.相同。返回
asyncio.TimerHandle
的实例,可用于取消callback.更改版本3.7:添加了context keyword-only参数。请参阅 PEP 567 了解更多详情.
更改版本3.7.1:在Python 3.7.0及更早版本中使用默认事件循环实施时,when与当前时间之间的差异不能超过一天。这已经在Python 3.7.1.
loop.
time
()-
中修复了根据事件循环的内部返回当前时间,作为
float
值单调时钟.
注意
超时(相对delay或绝对when)应该注意一天.
参见
asyncio.sleep()
功能
创造期货和任务
loop.
create_future
()-
创建
asyncio.Future
附加到事件循环的对象.这是在asyncio中创建Futures的首选方法。这个letsthird-party事件循环提供了Future对象的替代实现(具有更好的性能或工具).
版本3.5.2.
loop.
create_task
(coro)-
安排执行Coroutines.Return a
Task
object.第三方事件循环可以使用自己的
Task
用于互操作性。在这种情况下,结果类型是Task
.
loop.
set_task_factory
(factory)的子类-
设置一个将被
loop.create_task()
.使用的任务工厂如果factory是
None
默认任务工厂将被设置。否则,factory必须是callable,签名匹配(loop, coro)
,其中loop是对activeevent循环的引用,和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) -
打开到host和port.
指定的给定地址的流式传输连接。套接字族可以是
AF_INET
或AF_INET6
取决于在host(或family论点,如果提供的话).套接字类型
SOCK_STREAM
.protocol_factory必须是可调用的,返回 asyncio协议实现.
这个方法将尝试在后台建立连接。成功后,它返回一个
(transport, protocol)
pair.基本操作的时间顺序概要如下:
- 建立连接并为它创建一个传输.
- protocol_factory在没有参数的情况下被调用,并且预计会回复协议实例
- 协议实例通过调用它
connection_made()
方法。 - 一个
(transport, protocol)
元组成功返回
创建的传输是依赖于实现的双向流
其他参数:
-
ssl:如果给定而不是false,则创建SSL / TLS传输(默认情况下会创建纯TCP传输)。如果ssl是
ssl.SSLContext
对象,则此上下文用于创建传输;如果ssl是True
,使用从ssl.create_default_context()
返回的默认上下文参见
SSL / TLS安全考虑
-
server_hostname设置或覆盖将匹配目标服务器的证书的主机名。只应传递ssl不是
None
。默认使用host参数的值。如果host为空,则没有默认值,您必须为server_hostname传递avalue。如果server_hostname是一个emptystring,主机名匹配被禁用(这是一个严重的安全风险,允许潜在的中间人攻击). -
family, proto, flags是可选的地址系列,protocoland标志到传递给getaddrinfo()以获得host resolution。如果给出,这些都应该是来自相应的
socket
模块常量的整数. -
sock,如果给出,应该是现有的,已连接
socket.socket
运输使用的对象。如果给出sock,则不应指定host, port, family, proto, flags和local_addr -
local_addr//,如果给出,是
(local_host, local_port)
元组用于将套接字绑定到本地。local_host和local_port使用getaddrinfo()
进行查找,类似于host和port. -
ssl_handshake_timeout(对于TLS连接)在中止连接之前等待TLS握手完成的时间.
60.0
秒如果None
(默认).
版本3.7中新增: ssl_handshake_timeout参数
更改版本3.6:套接字选项对于所有TCP连接默认设置
TCP_NODELAY
。更改版本3.5:在
ProactorEventLoop
.中添加了对SSL / TLS的支持另见
open_connection()
功能是一个高级别的替代API。它返回一对(StreamReader
,StreamWriter
),可以直接在async / await代码中使用.
- 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 ) -
创建数据报连接.
套接字族可以是
AF_INET
,AF_INET6
或AF_UNIX
,具体取决于host(或family参数,如果提供).插座类型将是
SOCK_DGRAM
.protocol_factory必须是可赎回的协议implementation.
一个
(transport, protocol)
成功归还.其他论点:
- local_addr,如果给出,是
(local_host, local_port)
用于将套接字绑定到本地的元组。使用local_host查找local_port和getaddrinfo()
. - remote_addr,如果给出,是
(remote_host, remote_port)
用于将套接字连接到远程地址的元组。remote_host和remote_port使用getaddrinfo()
. - family, proto, flags查找是可选的地址族,protocoland标志要传递给
getaddrinfo()
host解析。如果给出,这些都应该是相应的整数socket
模块常量 - reuse_address告诉内核在
TIME_WAIT
状态下重用本地套接字,而不等待其自然超时出现。如果没有指定将自动设置为True
onUnix. - reuse_port告诉内核允许此端点绑定到同名端口,因为其他现有端点被绑定,只要它们在创建时都设置了此标志。Windows和某些Unix不支持此选项。如果
SO_REUSEPORT
常量未定义,则此功能不受支持. - allow_broadcast告诉内核允许此端点将消息发送到广播地址.
- sock可以选择指定,以便使用预先存在的,已连接的
socket.socket
对象来由传输使用。如果指定,local_addr和remote_addr应该省略(必须是None
).
在Windows上,用
ProactorEventLoop
,不支持此方法.参见 UDP echo客户端协议和 UDP echo服务器协议例句
在版本3.4.4中更改: family, proto, flags, reuse_address, reuse_port,*allow_broadcast,和sock参数被添加.
- local_addr,如果给出,是
- coroutine
loop.
create_unix_connection
(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None) -
创建一个Unix连接.
套接字族将
AF_UNIX
;sockettype将是SOCK_STREAM
.成功返回
(transport, protocol)
的元组path是一个Unix域套接字的名称,是必需的,除非sock参数已指定。抽象的Unix套接字,
str
,bytes
,和Path
路径得到支持.请参阅
loop.create_connection()
关于这个方法的参数的信息的方法.Availability:Unix .
新版本3.7: ssl_handshake_timeout参数.
改版3.7: path参数现在可以是路径类对象.
创建网络服务器
- 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地址回复
Server
object//Attguments:
- protocol_factory必须是一个可调用的协议实施
- // host参数可以设置为几种确定服务器监听位置的类型:
- 如果host是一个字符串,TCP服务器绑定到host.
- 指定的单个网络接口host是一个字符串序列,TCP服务器绑定到序列指定的所有网络接口.
- 如果host是一个空字符串或
None
假设所有接口,并返回多个套接字的列表(很可能是一个用于IPv4,另一个用于IPv6).
- family可以设置为
socket.AF_INET
或AF_INET6
强制套接字使用IPv4或IPv6。如果没有设置,family将根据主机名确定(默认为AF_UNSPEC
). - flags是
getaddrinfo()
. - sock可以选择指定以使用preexistingsocket对象。如果指定,则不能指定host和port。
- backlog是传递给
listen()
(默认为100). - ssl可以设为
SSLContext
实例,在已接受的连接上启用TLS . - reuse_address告诉内核在
TIME_WAIT
状态,无需等待其自然超时出现。如果没有指定将自动设置为True
onUnix. - 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:套接字选项
TCP_NODELAY
默认设置为所有TCP连接.更改版本3.5:在
ProactorEventLoop
.中添加了对SSL / TLS的支持在版本3.5.1中更改: host参数可以是一系列字符串.
参见
start_server()
function是一个更高级别的替代API,返回一对StreamReader
和StreamWriter
,可用于async / await代码.
- 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
pathare支持.请参阅
loop.create_server()
关于这种方法的参数的信息的方法.Availability:Unix .
新版本3.7: ssl_handshake_timeout和start_serving参数
更改版本3.7: path参数现在可以是
Path
object.
- coroutine
loop.
connect_accepted_socket
(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None) -
将已经接受的连接包装到传输/协议对中.
这个方法可以被接受asyncio外部连接但是使用asyncio来处理它们的服务器使用.
Parameters:
- protocol_factory必须是一个可调用的协议implementation
- sock是一个从
socket.accept
. - ssl返回的预先存在的套接字对象,可以设置为
SSLContext
,以便在接受的连接上启用SSL . - ssl_handshake_timeout是(对于SSL连接)在中止连接之前等待SSL握手完成的时间(秒)
60.0
秒如果None
(默认).
返回
(transport, protocol)
pair.版本3.7中新增: ssl_handshake_timeout参数
新版本3.5.3.
转移文件
- coroutine
loop.
sendfile
(transport, file, offset=0, count=None, *, fallback=True) -
在file上发送一个transport。返回bytessent的总数.
该方法使用高性能
os.sendfile()
如果可用.file必须是以二进制模式打开的常规文件对象.
offset告诉从哪里开始读取文件。如果指定,count是传输的字节总数,而不是到达文件,直到达到EOF。即使此方法引发错误,文件位置也会始终更新,并且
file.tell()
可以用来获取发送的实际字节数.fallback设置为
True
当平台不支持sendfile系统调用时(例如Unix上的Windows或SSL套接字),asyncio手动读取和发送文件.举起
SendfileNotAvailableError
如果系统不支持sendfile系统调用和fallback是False
.版本3.7.
TLS升级
- coroutine
loop.
start_tls
(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None) -
将现有的基于传输的连接升级到TLS.
返回一个新的传输实例,即protocol必须在await。transport实例传递到start_tls方法永远不能再使用了
参数:
- transport和protocol像
create_server()
和create_connection()
返回。 - sslcontext:
SSLContext
. - server_side通
True
当服务器端连接正在升级时(如create_server()
). - server_hostname:设置或覆盖目标服务器的证书将与之匹配的主机名.
- ssl_handshake_timeout(对于TLS连接)在中止连接之前完成TLS握手的时间(以秒为单位).
60.0
秒如果None
(默认).
版本3.7.
- transport和protocol像
新文件描述符
loop.
add_reader
(fd, callback, *args)-
开始监视fd文件描述符的读取可用性并使用指定的参数调用callback fd可用于读取
loop.
remove_reader
(fd)-
停止监视fd文件描述符的读取可用性.
loop.
add_writer
(fd, callback, *args)-
开始监视fd用于写入可用性的文件描述符并且使用指定的参数调用callback fd可以写入
使用
functools.partial()
来传递关键字参数到callback.
loop.
remove_writer
(fd)-
停止监视fd文件描述符的写入可用性
参见平台支持部分了解这些方法的一些限制.
直接使用套接字对象LY
通常,使用基于传输的API(例如loop.create_connection()
和loop.create_server()
)的协议实现比直接使用套接字的实现更快。但是,有一些用例当性能不重要时,并且使用socket
对象直接更方便.
- coroutine
loop.
sock_recv
(sock, nbytes) -
从nbytes到达sock。
socket.recv()
.的异步版本将接收到的数据作为字节对象返回.
sock必须是非阻塞套接字.
更改版本3.7:甚至虽然这个方法总是被记录为一个协程方法,但是在Python 3.7之前发布了
Future
。因为Python 3.7这是一个async def
方法
- coroutine
loop.
sock_recv_into
// (sock, buf) -
从sock接收数据到buf缓冲区。阻塞后建模
socket.recv_into()
method.返回写入缓冲区的字节数.
sock必须是一个非阻塞的socket.
新的版本3.7.
- coroutine
loop.
sock_sendall
(sock, data) -
发送data到sock插座。
socket.sendall()
.此方法继续发送到套接字,直到已发送所有数据data或发生错误。
None
成功归来。出错时,会引发异常。此外,无法确定连接结束时成功处理了多少数据(如果有的话).sock必须是非阻塞套接字.
在版本3.7中更改:即使该方法始终记录为协同方法,但在Python 3.7之前它返回
Future
。自Python 3.7以来,这是一个async def
方法
- coroutine
loop.
sock_connect
//(sock, address) -
将sock连接到address.
的远程套接字
socket.connect()
.sock的异步版本必须是非阻塞套接字.
版本3.5.2更改:
address
不再需要解决。sock_connect
将尝试通过调用address来检查socket.inet_pton()
是否已经解决。如果没有,loop.getaddrinfo()
将用于解决address.参见
loop.create_connection()
和asyncio.open_connection()
.
- coroutine
loop.
sock_accept
(sock) -
接受连接。模仿阻塞后
socket.accept()
方法套接字必须绑定到一个地址并侦听连接。返回值是一对
(conn, address)
其中conn是new套接字对象,可用于在连接上发送和接收数据,而address是地址绑定到连接另一端的插座.sock必须是一个非阻塞的插座.
更改版本3.7:即使该方法始终记录为coroutinemethod,在Python 3.7之前它返回
Future
。自Python 3.7起,这是一个async def
方法参见
loop.create_server()
和start_server()
.
- coroutine
loop.
sock_sendfile
(sock, file, offset=0, count=None, *, fallback=True) -
如果可能,使用高性能
os.sendfile
发送文件。返回发送的总字节数.//异步版本
socket.sendfile()
.sock必须是非阻塞的
socket.SOCK_STREAM
socket
.file必须是以二进制模式打开的常规文件对象.
offset告诉从哪里开始读取文件。如果指定,count是要传输的总字节数,而不是在文件到达EOF之前。即使此方法引发错误,文件位置也会始终更新,并且
file.tell()
可以用来获取发送的实际字节数.fallback,当设置为
True
时,使asyncio手动读取并在平台不支持sendfile系统调用时发送文件(例如Windows或SSL套接字)在Unix上).如果系统不支持
SendfileNotAvailableError
提升sendfile系统调用和fallback是False
.sock必须是非阻塞的socket.
新版本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中更改: getaddrinfo和getnameinfo方法总是记录为返回协程,但在Python 3.7之前,它们实际上是返回asyncio.Future
对象。从Python 3.7开始,方法是coroutines。
使用管道
- coroutine
loop.
connect_read_pipe
(protocol_factory, pipe) -
注册pipe的读取结束事件循环
protocol_factory必须是可调用的,返回 asyncio协议 implementation.
pipe是一个文件类对象.
返回对
(transport, protocol)
,其中transport支持ReadTransport
界面和protocol是protocol_factory.用
SelectorEventLoop
事件循环,pipe设置为非阻塞模式.
- coroutine
loop.
connect_write_pipe
(protocol_factory, pipe) -
记录pipe的写入结束事件循环
protocol_factory必须是一个可调用的 asyncio协议implementation.
pipe是文件般的对象.
返回对
(transport, protocol)
,transport支持WriteTransport
界面和protocol是protocol_factory.用
SelectorEventLoop
事件循环,pipe设置为非阻塞模式.
注意
SelectorEventLoop
不支持Windows上的上述方法。使用 ProactorEventLoop
而不是Windows.
也可以看看
loop.subprocess_exec()
和loop.subprocess_shell()
方法。
Unix信号
loop.
add_signal_handler
(signum, callback, *args)-
设置callback作为的处理程序signum信号。
回调将由loop,以及该事件循环的其他排队回调和可运行协同程序。与使用
signal.signal()
,使用此函数注册的回调允许与事件循环交互.如果信号编号无效或无法捕获,请回复
ValueError
.RaiseRuntimeError
如果设置处理程序有问题使用
functools.partial()
传递关键字参数到callback.就像
signal.signal()
,这个函数必须在mainthread.
loop.
remove_signal_handler
(sig)-
删除sig signal.
的处理程序如果删除了信号处理程序,则返回
True
,或者False
如果没有为给定信号设置处理程序.可用性:Unix.
参见
signal
module.
在线程或进程池中执行代码
- awaitable
loop.
run_in_executor
(executor, func, *args) -
为..作安排 func在指定的执行者中被召唤
executor论证应该是
concurrent.futures.Executor
实例。如果executor是None
.,则使用默认执行程序。例:
import asyncioimport concurrent.futuresdef 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
object.使用
functools.partial()
将关键字参数传递给func.在版本3.5.3中更改:
loop.run_in_executor()
不再配置它创建的线程池执行器的max_workers
,而是将其保存到线程池执行器(ThreadPoolExecutor
)来设置默认.
loop.
set_default_executor
(executor)-
设置executor因为
run_in_executor()
.executor使用的默认执行程序应该是ThreadPoolExecutor
.的实例自版本3.7以后不推荐使用使用不是
ThreadPoolExecutor
实例的执行程序是弃用并将在Python 3.9.executor中触发错误必须是
concurrent.futures.ThreadPoolExecutor
.
错误处理API的实例
允许自定义事件循环中处理异常的方式.
loop.
set_exception_handler
(handler)-
设置handler作为新的事件循环异常处理程序.
如果handler是
None
,将设置默认的异常处理程序。否则,handler必须是可调用的,具有(loop, context)
的签名匹配,其中loop
是对活动事件循环的引用,而context
是dict
包含异常细节的对象(参见call_exception_handler()
文档,了解有关上下文的详细信息).
loop.
get_exception_handler
()-
返回当前的异常处理程序,或
None
如果没有设置customexception处理程序.新版本3.5.2.
loop.
default_exception_handler
(context)-
默认异常处理程序.
当发生异常并且未设置exceptionhandler时调用此方法。这可以由想要遵循默认处理程序行为的自定义异常处理程序调用.
context参数与
call_exception_handler()
.
loop.
call_exception_handler
(context)中的含义相同-
调用当前事件循环异常处理程序.
context是
dict
包含以下键的对象(可能在将来的Python版本中引入新键):- ‘message’:错误消息;
- ‘exception’(可选):异常对象;
- ‘未来’(可选):
asyncio.Future
实例; - ‘句柄‘(可选):
asyncio.Handle
实例; - ‘协议’(可选):协议实例;
- ‘transport’(可选):运输实例;
- ‘插座’(可选):
socket.socket
instance.
注意
这个方法不应该在sublassedevent循环中重载。对于自定义异常处理,使用
set_exception_handler()
方法
启用调试模式
loop.
get_debug
()-
获取事件循环的调试模式(
bool
)如果环境变量
True
设置为非空,则默认值为PYTHONASYNCIODEBUG
string,False
otherwise.
loop.
set_debug
(enabled: bool)-
设置事件循环的调试模式.
更改版本3.7:新的
-X dev
命令行选项现在也可用于启用调试模式.
另见
asyncio的调试模式.
运行子进程
本小节中描述的方法是低级的。在regularasync / await代码中考虑使用高级asyncio.create_subprocess_shell()
和asyncio.create_subprocess_exec()
便利功能改为.
注意
上的默认asyncio事件循环不支持过程。有关详细信息,请参阅 Windows上的子进程支持
- coroutine
loop.
subprocess_exec
(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) -
从args.
args指定的一个或多个字符串参数创建子进程必须是由以下表示的字符串列表:
str
;- 或
bytes
,编码为文件系统编码.
第一个字符串指定程序可执行文件,其余字符串指定参数。一起,字符串形成了程序的
argv
这与使用
subprocess.Popen
调用的标准库shell=False
类相似,并且作为第一个参数传递的字符串列表;但是,Popen
采用单个参数,即字符串列表,subprocess_exec需要多个字符串参数.protocol_factory必须是一个可调用的返回
asyncio.SubprocessProtocol
类。其他参数:
-
stdin:表示要使用
connect_write_pipe()
连接到子进程标准输入流的管道的文件类对象,或者subprocess.PIPE
常数(默认)。默认情况下,将创建并连接一个新管. -
stdout:一个类似文件的对象,表示使用
connect_read_pipe()
,或subprocess.PIPE
常量(默认)。默认情况下,将创建并连接新的管道. -
stderr:使用
connect_read_pipe()
,或subprocess.PIPE
(默认)或subprocess.STDOUT
constants.默认情况下,将创建并连接新管道。指定
subprocess.STDOUT
时,子进程’standarderror流将连接到与standardoutput流相同的管道. -
所有其他关键字参数都传递给
subprocess.Popen
而没有解释,除了bufsize, universal_newlines和shell之外,根本不应该指定
参见构造函数
subprocess.Popen
关于其他参数的文档的类.回复一对
(transport, protocol)
,其中transport符合asyncio.SubprocessTransport
基类和protocol是一个对象由protocol_factory.
- coroutine
loop.
subprocess_shell
(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) -
从cmd创建一个子进程,可以是
str
或bytes
字符串编码到文件系统编码,使用平台的“shell”语法.这类似于标准库
subprocess.Popen
用打来的课shell=True
.protocol_factory必须是一个可调用的返回
SubprocessProtocol
类。见
subprocess_exec()
有关其余参数的详细信息.返回一对
(transport, protocol)
,transport符合SubprocessTransport
基类和protocol是protocol_factory.
注意
应用程序有责任确保适当引用所有空格和特殊字符以避免shell注入漏洞。shlex.quote()
函数可以用来正确地转义将用于构造shell命令的字符串中的空格和特殊字符.
Callback句柄
- 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.
Server对象
服务器对象由loop.create_server()
,loop.create_unix_server()
, start_server()
和start_unix_server()
functions.
创建。不要直接实例化该对象.
- class
asyncio.
Server
-
Server对象是异步上下文管理器。用于
async with
声明,当async with
语句完成时,保证Server对象被关闭并且不接受新连接:srv = await loop.create_server(...)async with srv: # some code# At this point, srv is closed and no longer accepts new connections.
在版本3.7中更改:服务器对象是一个异步上下文管理器,因为Python 3.7.
close
()-
停止服务:关闭侦听套接字并将
sockets
属性设置为None
.代表现有传入客户端连接的套接字保持打开状态
服务器异步关闭,使用
wait_closed()
coroutine要等到服务器关闭.
- coroutine
start_serving
() -
开始接受连接.
这种方法是幂等的,所以当服务器已经在服务时可以调用它.
start_serving仅限关键字的参数
loop.create_server()
和asyncio.start_server()
允许创建最初不接受连接的Server对象。在这种情况下Server.start_serving()
或Server.serve_forever()
可用于使服务器开始接受连接.新版本3.7.
- coroutine
serve_forever
() -
开始接受连接直到协程被取消。取消
serve_forever
任务导致serverto关闭.如果服务器已经接受连接,则可以调用此方法。只有一个
serve_forever
任务可以存在Server object.例如:
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.
- coroutine
wait_closed
() -
等到
close()
方法完成.
事件循环实现
asyncio附带两个不同的事件循环实现:SelectorEventLoop
和ProactorEventLoop
.
默认情况下,asyncio配置为使用SelectorEventLoop
在所有平台上
- class
asyncio.
SelectorEventLoop
-
一个基于
selectors
模块的事件循环使用最有效的selector可用于给定的平台。也可以手动配置要使用的精确选择器实现:
import asyncioimport selectorsselector = selectors.SelectSelector()loop = asyncio.SelectorEventLoop(selector)asyncio.set_event_loop(loop)
可用性:Unix,Windows.
示例
注意本节中的所有例子故意展示了如何使用低级事件循环API,例如loop.run_forever()
和loop.call_soon()
。现代的asyncio应用程序很少需要以这种方式编写;考虑使用像asyncio.run()
.
call_soon()
使用loop.call_soon()
方法调度acallback的示例。回调显示"Hello World"
,然后停止事件循环:
import asynciodef 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 用coroutine创建的示例和run()
function.
用call_later()显示当前日期
每秒显示当前日期的回调示例。thecallback使用loop.call_later()
5秒后重新安排自己的方法,然后停止事件循环:
import asyncioimport datetimedef 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.0loop.call_soon(display_date, end_time, loop)# Blocking call interrupted by loop.stop()try: loop.run_forever()finally: loop.close()
参见
一个类似的当前日期用coroutine创建的例子和run()
功能
观察读取事件的文件描述符
等待文件描述符使用loop.add_reader()
方法接收到一些数据,然后关闭事件循环:
import asynciofrom socket import socketpair# Create a pair of connected file descriptorsrsock, 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 eventloop.add_reader(rsock, reader)# Simulate the reception of data from the networkloop.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()
为SIGINT和SIGTERM设置信号处理程序
(这个signals
示例仅适用于Unix。)
使用SIGINT
方法SIGTERM
文章导航loop.add_signal_handler()
事件循环方法// //为
import asyncioimport functoolsimport osimport signaldef ask_exit(signame): 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)) 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())
评论被关闭。