You are here:  Home » Python » 事件循环 – 异步I / O(Python教程)(参考资料)

事件循环

前言

事件循环是每个asyncio应用程序的核心。事件循环运行异步任务和回调,执行networkIO操作,并运行子进程.

应用程序开发人员通常应该使用高级asyncio函数,例如asyncio.run(),并且很少需要引用loopobject或调用其方法。本节主要面向低级代码,库和框架的作者,他们需要更好地控制事件循环行为.

获取事件循环

以下低级函数可用于获取,设置或创建事件循环:

asyncio.get_running_loop

返回当前操作系统线程中的运行事件循环

如果没有运行事件循环,则会引发RuntimeError。此函数只能从协程或回调调用.

新版本3.7.

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的参考文档;
  • 回调句柄部分记录了HandleTimerHandle实例,这些实例是从调度方法返回的,例如loop.call_soon()loop.call_later();
  • 服务器对象部分文档类型返回fromevent循环方法,如loop.create_server();
  • 事件循环实现部分记录了SelectorEventLoopProactorEventLoop类;
  • 示例部分展示了如何使用一些eventloop API .

事件循环方法

事件循环有低级 API用于以下内容:

  • 运行和停止循环
  • 调度回调
  • 安排延迟回调
  • 创建期货和任务
  • 打开网络连接
  • 创建网络服务器
  • 传输文件
  • TLS升级
  • 看文件描述符
  • 直接使用套接字对象
  • DNS
  • 使用管道
  • Unix信号
  • 在线程或进程中执行代码pool
  • 错误处理API
  • 启用调试模式
  • 运行子进程

运行和停止循环

loop.run_until_completefuture

运行到futureFuture的一个例子)已完成

如果论证是协程对象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_sooncallback, *args, context=None

安排一个 callback跟打电话args在事件循环的下一次迭代中的参数

//按照它们的注册顺序调用。每次回调都会被调用一次.

一个可选的关键字context参数允许指定自定义contextvars.Context为了 callback运行。当没有context提供了

的一个例子asyncio.Handle返回,以后可以用来取消回调.

这种方法不是线程安全的

loop.call_soon_threadsafecallback, *args, context=None

的线程安全变体call_soon()。必须使用toschedule回调from another thread.

并发和多线程文档部分.

更改版本3.7:添加了context keyword-only参数。见 PEP 567 了解更多详情.

注意

大多数asyncio调度函数不允许传递关键字参数。为此,使用functools.partial()

# will schedule "print("Hello", flush=True)"loop.call_soon(    functools.partial(print, "Hello", flush=True))

使用部分对象通常比使用lambdas更方便,因为asyncio可以在调试和错误消息中更好地渲染部分对象.

调度延迟回调

事件循环提供了调度回调函数的机制,以便在将来的某个时刻调用。事件循环使用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_atwhen, 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_factoryfactory)的子类

设置一个将被loop.create_task().

使用的任务工厂如果factoryNone默认任务工厂将被设置。否则,factory必须是callable,签名匹配(loop, coro),其中loop是对activeevent循环的引用,和coro是一个协程对象。可调用的必须返回asyncio.Future – 兼容对象.

loop.get_task_factory)

返回任务工厂或None如果默认的是在使用中

打开网络连接

coroutine loop.create_connectionprotocol_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

打开到hostport.

指定的给定地址的流式传输连接。套接字族可以是AF_INETAF_INET6取决于在host(或family论点,如果提供的话).

套接字类型SOCK_STREAM.

protocol_factory必须是可调用的,返回 asyncio协议实现.

这个方法将尝试在后台建立连接。成功后,它返回一个(transport, protocol) pair.

基本操作的时间顺序概要如下:

  1. 建立连接并为它创建一个传输.
  2. protocol_factory在没有参数的情况下被调用,并且预计会回复协议实例
  3. 协议实例通过调用它connection_made()方法。
  4. 一个 (transport, protocol)元组成功返回

创建的传输是依赖于实现的双向流

其他参数:

  • ssl:如果给定而不是false,则创建SSL / TLS传输(默认情况下会创建纯TCP传输)。如果sslssl.SSLContext对象,则此上下文用于创建传输;如果sslTrue,使用从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, flagslocal_addr

  • local_addr//,如果给出,是(local_host, local_port)元组用于将套接字绑定到本地。local_hostlocal_port使用getaddrinfo()进行查找,类似于hostport.

  • 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_INET6AF_UNIX,具体取决于host(或family参数,如果提供).

插座类型将是SOCK_DGRAM.

protocol_factory必须是可赎回的协议implementation.

一个(transport, protocol)成功归还.

其他论点:

  • local_addr,如果给出,是(local_host, local_port)用于将套接字绑定到本地的元组。使用local_host查找local_portgetaddrinfo().
  • remote_addr,如果给出,是(remote_host, remote_port)用于将套接字连接到远程地址的元组。remote_hostremote_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_addrremote_addr应该省略(必须是None).

在Windows上,用ProactorEventLoop,不支持此方法.

参见 UDP echo客户端协议 UDP echo服务器协议例句

在版本3.4.4中更改: family, proto, flags, reuse_address, reuse_port,*allow_broadcast,和sock参数被添加.

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_serverprotocol_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_STREAMport host地址

回复Serverobject

//Attguments:

  • protocol_factory必须是一个可调用的协议实施
  • // host参数可以设置为几种确定服务器监听位置的类型:
    • 如果host是一个字符串,TCP服务器绑定到host.
    • 指定的单个网络接口host是一个字符串序列,TCP服务器绑定到序列指定的所有网络接口.
    • 如果host是一个空字符串或None假设所有接口,并返回多个套接字的列表(很可能是一个用于IPv4,另一个用于IPv6).
  • family可以设置为socket.AF_INETAF_INET6强制套接字使用IPv4或IPv6。如果没有设置,family将根据主机名确定(默认为AF_UNSPEC).
  • flagsgetaddrinfo().
  • sock可以选择指定以使用preexistingsocket对象。如果指定,则不能指定hostport
  • 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_timeoutstart_serving参数

更改版本3.6:套接字选项TCP_NODELAY默认设置为所有TCP连接.

更改版本3.5:ProactorEventLoop.

中添加了对SSL / TLS的支持在版本3.5.1中更改: host参数可以是一系列字符串.

参见

start_server()function是一个更高级别的替代API,返回一对StreamReaderStreamWriter,可用于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,和Pathpathare支持.

请参阅loop.create_server()关于这种方法的参数的信息的方法.

Availability:Unix .

新版本3.7: ssl_handshake_timeoutstart_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.sendfiletransport, 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系统调用和fallbackFalse.

版本3.7.

TLS升级

coroutine loop.start_tlstransport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None

将现有的基于传输的连接升级到TLS.

返回一个新的传输实例,即protocol必须在awaittransport实例传递到start_tls方法永远不能再使用了

参数:

  • transportprotocolcreate_server()create_connection()返回。
  • sslcontextSSLContext.
  • server_sideTrue当服务器端连接正在升级时(如create_server()).
  • server_hostname:设置或覆盖目标服务器的证书将与之匹配的主机名.
  • ssl_handshake_timeout(对于TLS连接)在中止连接之前完成TLS握手的时间(以秒为单位).60.0秒如果None(默认).

版本3.7.

新文件描述符

loop.add_readerfd, callback, *args

开始监视fd文件描述符的读取可用性并使用指定的参数调用callback fd可用于读取

loop.remove_readerfd

停止监视fd文件描述符的读取可用性.

loop.add_writer(fd, callback, *args)

开始监视fd用于写入可用性的文件描述符并且使用指定的参数调用callback fd可以写入

使用functools.partial() 来传递关键字参数callback.

loop.remove_writerfd

停止监视fd文件描述符的写入可用性

参见平台支持部分了解这些方法的一些限制.

直接使用套接字对象LY

通常,使用基于传输的API(例如loop.create_connection()loop.create_server())的协议实现比直接使用套接字的实现更快。但是,有一些用例当性能不重要时,并且使用socket对象直接更方便.

coroutine loop.sock_recv (sock, nbytes)

nbytes到达socksocket.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)

发送datasock插座。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_acceptsock

接受连接。模仿阻塞后socket.accept()方法

套接字必须绑定到一个地址并侦听连接。返回值是一对(conn, address)其中connnew套接字对象,可用于在连接上发送和接收数据,而address是地址绑定到连接另一端的插座.

sock必须是一个非阻塞的插座.

更改版本3.7:即使该方法始终记录为coroutinemethod,在Python 3.7之前它返回Future。自Python 3.7起,这是一个async def方法

参见

loop.create_server()start_server().

coroutine loop.sock_sendfilesock, file, offset=0, count=None, *, fallback=True

如果可能,使用高性能os.sendfile发送文件。返回发送的总字节数.

//异步版本socket.sendfile().

sock必须是非阻塞的socket.SOCK_STREAMsocket.

file必须是以二进制模式打开的常规文件对象.

offset告诉从哪里开始读取文件。如果指定,count是要传输的总字节数,而不是在文件到达EOF之前。即使此方法引发错误,文件位置也会始终更新,并且file.tell()可以用来获取发送的实际字节数.

fallback,当设置为True时,使asyncio手动读取并在平台不支持sendfile系统调用时发送文件(例如Windows或SSL套接字)在Unix上).

如果系统不支持SendfileNotAvailableError提升sendfile系统调用和fallbackFalse.

sock必须是非阻塞的socket.

新版本3.7.

DNS

coroutine loop.getaddrinfo (host, port, *, family=0, type=0, proto=0, flags=0)

异步版socket.getaddrinfo().

coroutine loop.getnameinfosockaddr, flags=0

socket.getnameinfo().

的异步版本在版本3.7中更改: getaddrinfogetnameinfo方法总是记录为返回协程,但在Python 3.7之前,它们实际上是返回asyncio.Future对象。从Python 3.7开始,方法是coroutines。

使用管道

coroutine loop.connect_read_pipeprotocol_factory, pipe

注册pipe的读取结束事件循环

protocol_factory必须是可调用的,返回 asyncio协议 implementation.

pipe是一个文件类对象.

返回对(transport, protocol),其中transport支持ReadTransport界面和protocolprotocol_factory.

SelectorEventLoop事件循环,pipe设置为非阻塞模式.

coroutine loop.connect_write_pipe(protocol_factory, pipe)

记录pipe的写入结束事件循环

protocol_factory必须是一个可调用的 asyncio协议implementation.

pipe文件般的对象.

返回对(transport, protocol)transport支持WriteTransport界面和protocolprotocol_factory.

SelectorEventLoop事件循环,pipe设置为非阻塞模式.

注意

SelectorEventLoop不支持Windows上的上述方法。使用 ProactorEventLoop而不是Windows.

也可以看看

loop.subprocess_exec()loop.subprocess_shell()方法。

Unix信号

loop.add_signal_handlersignum, callback, *args

设置callback作为的处理程序signum信号。

回调将由loop,以及该事件循环的其他排队回调和可运行协同程序。与使用signal.signal(),使用此函数注册的回调允许与事件循环交互.

如果信号编号无效或无法捕获,请回复ValueError.Raise RuntimeError如果设置处理程序有问题

使用functools.partial() 传递关键字参数callback.

就像signal.signal(),这个函数必须在mainthread.

loop.remove_signal_handler(sig)

删除sig signal.

的处理程序如果删除了信号处理程序,则返回True,或者False如果没有为给定信号设置处理程序.

可用性:Unix.

参见

signalmodule.

在线程或进程池中执行代码

awaitable loop.run_in_executorexecutor, func, *args

为..作安排 func在指定的执行者中被召唤

executor论证应该是concurrent.futures.Executor实例。如果executorNone.

,则使用默认执行程序。例:

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_executorexecutor

设置executor因为run_in_executor().executor使用的默认执行程序应该是ThreadPoolExecutor.

的实例自版本3.7以后不推荐使用使用不是ThreadPoolExecutor实例的执行程序是弃用并将在Python 3.9.

executor中触发错误必须是concurrent.futures.ThreadPoolExecutor.

错误处理API的实例

允许自定义事件循环中处理异常的方式.

loop.set_exception_handlerhandler

设置handler作为新的事件循环异常处理程序.

如果handlerNone,将设置默认的异常处理程序。否则,handler必须是可调用的,具有(loop, context)的签名匹配,其中loop是对活动事件循环的引用,而contextdict包含异常细节的对象(参见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_handlercontext)中的含义相同

调用当前事件循环异常处理程序.

contextdict包含以下键的对象(可能在将来的Python版本中引入新键):

  • ‘message’:错误消息;
  • ‘exception’(可选):异常对象;
  • ‘未来’(可选):asyncio.Future实例;
  • 句柄‘(可选):asyncio.Handle实例;
  • ‘协议’(可选):协议实例;
  • ‘transport’(可选):运输实例;
  • ‘插座’(可选):socket.socketinstance.

注意

这个方法不应该在sublassedevent循环中重载。对于自定义异常处理,使用set_exception_handler()方法

启用调试模式

loop.get_debug

获取事件循环的调试模式(bool

如果环境变量True设置为非空,则默认值为PYTHONASYNCIODEBUGstring,Falseotherwise.

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.STDOUTconstants.

    默认情况下,将创建并连接新管道。指定subprocess.STDOUT时,子进程’standarderror流将连接到与standardoutput流相同的管道.

  • 所有其他关键字参数都传递给subprocess.Popen而没有解释,除了bufsize, universal_newlinesshell之外,根本不应该指定

参见构造函数subprocess.Popen关于其他参数的文档的类.

回复一对(transport, protocol),其中transport符合asyncio.SubprocessTransport基类和protocol是一个对象由protocol_factory.

coroutine loop.subprocess_shellprotocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs

cmd创建一个子进程,可以是strbytes字符串编码到文件系统编码,使用平台的“shell”语法.

这类似于标准库subprocess.Popen用打来的课shell=True.

protocol_factory必须是一个可调用的返回SubprocessProtocol类。

subprocess_exec()有关其余参数的详细信息.

返回一对(transport, protocol)transport符合SubprocessTransport基类和protocolprotocol_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要等到服务器关闭.

get_loop

返回与服务器对象关联的事件循环.

新版本3.7.

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()方法完成.

sockets

socket.socket服务器正在监听的对象列表,或None如果服务器关闭了

更改版本3.7:在Python 3.7之前Server.sockets用于直接返回内部服务器套接字列表。在3.7中返回该列表的副本.

事件循环实现

asyncio附带两个不同的事件循环实现:SelectorEventLoopProactorEventLoop.

默认情况下,asyncio配置为使用SelectorEventLoop在所有平台上

class asyncio.SelectorEventLoop

一个基于selectors模块的事件循环

使用最有效的selector可用于给定的平台。也可以手动配置要使用的精确选择器实现:

import asyncioimport selectorsselector = selectors.SelectSelector()loop = asyncio.SelectorEventLoop(selector)asyncio.set_event_loop(loop)

可用性:Unix,Windows.

class asyncio.ProactorEventLoop

使用“I / O完成端口”(IOCP)的Windows事件循环.

可用性:Windows.

如何在Windows上使用ProactorEventLoop的例子:

import asyncioimport sysif sys.platform == "win32":    loop = asyncio.ProactorEventLoop()    asyncio.set_event_loop(loop)

另见

关于I / O完成端口的MSDN文档

class asyncio.AbstractEventLoop

符合asyncio的事件循环的抽象基类.

事件循环方法部分列出了AbstractEventLoop的另一种实现应该定义的所有方法.

示例

注意本节中的所有例子故意展示了如何使用低级事件循环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()

参见

  • 类似示例使用传输,协议和loop.create_connection()方法
  • 另一个类似的示例使用高级asyncio.open_connection()函数和streams.

为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())

评论被关闭。