python3 asyncio官方文档中文版

  1. 事件循环基类
  2. 事件循环基类
    事件循环是由asyncio提供的核心执行装置。它提供了多种服务,包括:

注册、执行和关闭延时调用(超时)
为各类通讯建立客户端和服务端传输
为一个外部程序通讯启动子进程和相关的传输
把高成本的函数调用委托到线程池
class asyncio.BaseEventLoop
   此类是一个实现细节。此类是AbstractEventLoop的子类,是你在asyncio中找到的具体事件循环类的基类。它不该该被直接使用,而是使用AbstractEventLoop来代替它。BaseEventLoop不该该被第三方代码继承,它的内部接口并不稳定。shell

class asyncio.AbstractEventLoop
   事件循环抽象基类。
   这个类不是线程安全的。windows

1.1. 运行事件循环
AbstractEventLoop.run_forever()
   一直运行直到stop()被调用。若是stop()在run_forever()以前被调用,它将轮询一次I/O selector(timeout为0),而后运行全部响应I/O事件的回调(以及那些已经被安排的回调),而后退出。若是stop()在run_forever()运行时被调用,它将运行当前的一批回调而后退出。请注意,那些被回调函数安排的回调不会在这种状况下运行;它们将会在下一次run_forever被调用时运行。
改动于3.5.1版本。安全

AbstractEventLoop.run_until_complete(future)
   一直运行直到future运行完成。
   若是参数是一个协程对象,它将被ensure_future()打包。
   返回Future的结果,或者引起它的异常。网络

AbstractEventLoop.stop()
   中止运行事件循环。
   它将在一个适当的时机使得run_forever()退出。
改动于3.5.1版本。多线程

AbstractEventLoop.is_closed()
   当事件循环关闭时返回True。
新增于3.4.2版本。并发

AbstractEventLoop.close()
   关闭事件循环。这个事件循环必须没有在运行。挂起的回调将会丢失。
   此方法清空队列、关闭执行器,且不会等待执行器运行结束。
   此方法是幂等且不可逆的。在此方法调用以后不该该调用任何其余方法。socket

1.2. 调用
大多数asyncio函数不接受参数。若是你想给你的回调函数一些参数,使用functools.partial()。例如,loop.call_soon(functools.partial(print, "Hello", flush=True))将会调用print("Hello", flush=True)。async

注意:functools.partial()比lambda方法更好,由于asyncio能检查functools.partial()对象,使得能在调试模式下展现参数。相比之下使用lambda会有糟糕的表现。ide

AbstractEventLoop.call_soon(callback, *args)
   安排尽快调用这个callback(回调)。这个callback会在call_soon()返回、当控制权返回事件循环时被调用。
   这个操做是一个先入先出队列,多个call_soon()注册了多个callback会按照它们的顺序依次被调用。每一个callback都只会被调用一次。
   callback后面的全部参数会在callback被调用时传递给callback。
   返回值是asyncio.Handle的一个实例,用于停止这个callback。
   (可使用functools.partial()来给callback传递参数)函数

AbstractEventLoop.call_soon_threadsafe(callback, *args)
   相似call_soon(),可是是线程安全的。
   能够参考使用asyncio开发的 并发和多线程 段落。

1.3. 延时调用
事件循环有本身的内部时钟用于计算超时。这个时钟依赖于(特定平台的)事件循环来执行;理想状况下它是一个单调时钟(monotonic clock)。一般它是一个不一样于time.time()的时钟。

注意:超时(相对延时或绝对时刻)不该该超过一天。

AbstractEventLoop.call_later(delay, callback, *args)
   安排一个callback在delay秒以后被调用(delay能够是int和float)。
   返回值是asyncio.Handle的一个实例,用于停止这个callback。
   每次调用call_later()都有callback将被调用一次。若是多个回调被安排在同一时刻调用,谁先被调用是不肯定的。
   可选参数args将被传递给callback做为调用时的参数。若是你想给callback传递带名字的参数,把它们包起来或者用functools.partial()。

AbstractEventLoop.call_at(when, callback, *args)
   安排callback在给定的时间戳when(int或者float)时调用;用AbstractEventLoop.time()做为参考。
   这个方法的行为和AbstractEventLoop.call_later()同样。
   返回值是asyncio.Handle的一个实例,用于停止这个callback。

AbstractEventLoop.time()
   返回当前时间,一个float值,根据事件循环的内部时钟。

1.4. Futures
AbstractEventLoop.create_future()
   建立一个关联到这个事件循环的asyncio.Future对象。
   这是asyncio中建立Future的首选方式,做为事件循环的实现能够提供Future类的代替实现(有更好的性能或表现)。
新增于3.5.2版本。

1.5. 任务
AbstractEventLoop.create_task(coro)
   安排一个协程对象的执行:把它包装在一个future里。返回一个任务(Task)对象。
   第三方事件循环可使用他们本身的Task子类来交互。在这种状况下,返回值类型是Task的子类。
   这个方法是Python 3.4.2版本加入的。使用async()能够支持旧的Python版本。
新增于3.4.2版本。

AbstractEventLoop.set_task_factory(factory)
   为AbstractEventLoop.create_task()设置一个task的工厂。
   若是factory参数是None,将会设置为默认工厂。
   若是factory参数是可被调用(callable)的,他应该能够接受(loop, coro)做为参数,loop是一个可用的事件循环,coro是协程对象。它必须返回一个asyncio.Future的兼容对象。
新增于3.4.4版本。

AbstractEventLoop.get_task_factory()
   返回任务工厂,若是用的是默认的工厂,返回None。
新增于3.4.4版本。

1.6. 建立链接
coroutine AbstractEventLoop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None)
   建立一个链接到给定的host(主机)和port(端口)的流传输链接:socket family是AF_INET仍是AF_INET6取决于host(或者指定了family参数),socket type是SOCK_STREAM。protocol_factory必须是可被调用(callable)的且返回一个传输(protocol)实例。
   这是一个协程方法,它将在后台默默地创建一个链接。创建成功的时候,返回一个(transport, protocol)元组((传输,协议)对)。

   按时间顺序的大概底层操做以下:

链接创建,建立一个传输(transport)来表明它。
protocol_factory被调用(没有参数),返回一个协议(protocol)实例。
这个协议(protocol)实例和传输(transport)捆绑在一块儿,其connection_made()方法被调用。
这个协程成功地返回(transport, protocol)对。
   建立的传输是一个依赖于实现的双向流。

注意:protocol_factory能够是任意的可被调用(callable)对象,不必定要是一个类。例如,你想使用一个预先建立的协议实例,你能够写lambda: my_protocol。

   这些选项能够改变链接建立方式:

ssl:若是给了这个参数且不为false,将会建立一个SSL/TLS传输(默认是一个普通的TCP传输被建立)。若是ssl是一个ssl.SSLContext对象,这个上下文将被用于建立传输;若是ssl是True,一个带有一些未被指明的默认设置的上下文将被使用。(能够去参考官方文档ssl章节的SSL/TLS security considerations段落)
server_hostname,只能和ssl参数一块儿使用,用于设置或覆盖将要匹配目标主机证书的主机名。默认会使用host参数。若是host参数为空,没有默认值,你必须填写server_hostname参数的值。若是server_hostname是一个空字符串,主机名匹配就被禁用了(这很是不安全,可能会产生中间人攻击)。
family,proto,flags是可选的地址族(address family)、协议(protocol)、位掩码(flags),来传给getaddrinfo()进行host参数的域名解析。若是给定这些参数,这些应该都是相应的socket模块的常量整数。
sock,若是给定这个参数,它必须是已存在的、已链接的socket.socket对象,来用于传输。若是给定了这个参数,host、port、family、proto、flags和local_addr参数都不该该给定。
local_addr,若是给定了这个参数,它应该是一个来用绑定到本地socket的(local_host, local_port)元组((本地地址,本地端口)元组)。local_host和local_port将使用getaddrinfo()来查询,相似于host和port参数。
改动于3.5版本:SSL/TLS如今支持Windows上的ProactorEventLoop了。

还能够看看open_connection()函数,它能够得到(StreamReader, StreamWriter)对,而不是一个协议。

coroutine AbstractEventLoop.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)
   建立一个数据报链接:socket family是AF_INET仍是AF_INET6取决于host(或者指定了family参数),socket type是SOCK_DGRAM。protocol_factory必须是可被调用(callable)的且返回一个传输(protocol)实例。
   这是一个协程方法,它将在后台默默地创建一个链接。创建成功的时候,返回一个(transport, protocol)元组((传输,协议)对)。
   这些选项能够改变链接建立方式:

local_addr,若是给定了这个参数,它应该是一个来用绑定到本地socket的(local_host, local_port)元组((本地地址,本地端口)元组)。local_host和local_port将使用getaddrinfo()来查询。
remote_addr,若是给定了这个参数,它应该是一个来用绑定到远程地址的socket的(remote_host, remote_port)元组((本地地址,本地端口)元组)。remote_host和remote_port将使用getaddrinfo()来查询。
family,proto,flags是可选的地址族(address family)、协议(protocol)、位掩码(flags),来传给getaddrinfo()进行host参数的域名解析。若是给定这些参数,这些应该都是相应的socket模块的常量整数。
reuse_address,这个参数告诉内核在TIME_WAIT状态下重用本地的socket,而不是等待它天然的超时过时。若是没有指定这个参数,在UNIX下默认设为True。
reuse_port,这个参数告诉内核容许这个端点绑定到这个端口,即便有另外的已存在的端点绑定了这个端口,只要它们在建立时也设置了这个参数就行。这个选项在Windows和部分UNIX上不被支持。若是SO_REUSEPORT这个常量没有被定义,那这个能力就是不支持的。
allow_broadcast,这个参数告诉内核容许这个端点发送消息给广播地址。
sock参数能够被指定来使用一个先前存在的、已链接的socket.socket对象来用于传输。若是指定了这个参数,local_addr和remote_addr必须被省略(必须为None)。
   在Windows上的ProactorEventLoop循环里,这个方法还不被支持。
   能够参考UDP客户端协议和UDP服务端协议实例。

coroutine AbstractEventLoop.create_unix_connection(protocol_factory, path, *, ssl=None, sock=None, server_hostname=None)
   建立一个UNIX链接:socket family是AF_UNIX,socket type是SOCK_STREAM。AF_UNIX是用来进行同一机器上的不一样进程间的高效通讯的。
   这是一个协程方法,它将在后台默默地创建一个链接。创建成功的时候,返回一个(transport, protocol)元组((传输,协议)对)。
   参数能够参考AbstractEventLoop.create_connection()方法的参数。
   仅适用于:UNIX。

1.7. 建立监听链接
coroutine AbstractEventLoop.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)
   建立一个TCP服务端(socket type是SOCK_STREAM),绑定到host和port参数(主机和端口)。
   返回一个Server对象,它的sockets属性包含了已建立的socket。使用Server.close()方法来中止这个服务端:关闭监听的sockets。
   参数:

host参数能够是一个字符串,在这种状况下TCP服务端绑定到host和port参数。host参数也能够是字符串序列,这种状况下TCP服务端绑定到host序列里的全部主机。若是host是空字符串或者None,全部的接口都被假定,返回一个有多个socket的list(最可能的用于IPv4的一个和IPv6的一个)。
family参数能够设置为socket.AF_INET或者AF_INET6来使socket强制使用IPv4或者IPv6。若是没有设置就会取决于host(默认是socket.AF_UNSPEC)。
flags是用于的getaddrinfo()的位掩码。
sock参数能够被指定,用来使用先前存在的socket对象。若是指定了,host和port参数应该被省略(必须为None)。
backlog参数是传递给listen()方法的最大等待链接数(默认为100)。
ssl参数能够设置一个SSLContext对象来在一个接受的链接上启用SSL。
reuse_address,这个参数告诉内核在TIME_WAIT状态下重用本地的socket,而不是等待它天然的超时过时。若是没有指定这个参数,在UNIX下默认设为True。
reuse_port,这个参数告诉内核容许这个端点绑定到这个端口,即便有另外的已存在的端点绑定了这个端口,只要它们在建立时也设置了这个参数就行。这个选项在Windows上不被支持。
   这个是一个协程方法。

改动于3.5版本:SSL/TLS如今支持Windows上的ProactorEventLoop了。

还能够看看start_server()函数,它建立一个(StreamReader, StreamWriter)对,而且回调一个方法。

改动于3.5.1版本:host参数如今能够是一个字符串序列。

coroutine AbstractEventLoop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None)
   相似于AbstractEventLoop.create_server(),可是具体的socket family是AF_UNIX。
   这个是一个协程方法。
   仅适用于:UNIX。

1.8. 监视文件描述符(file descriptor)
对于Windows上的SelectorEventLoop,只有socket处理被支持(例如:管道文件描述符不被支持)。
对于Windows上的ProactorEventLoop,这些方法都不被支持。

AbstractEventLoop.add_reader(fd, callback, *args)
   开始监视可读的文件描述符fd,而后会传递给定的args来调用callback。
   (可使用functools.partial()来给callback传递参数)

AbstractEventLoop.remove_reader(fd)
   中止监视这个可读的文件描述符。

AbstractEventLoop.add_writer(fd, callback, *args)
   开始监视可写的文件描述符fd,而后会传递给定的args来调用callback。
   (可使用functools.partial()来给callback传递参数)

AbstractEventLoop.remove_writer(fd)
   中止监视这个可写的文件描述符。

最下面有这些方法的实例。

1.9. 低级socket操做
coroutine AbstractEventLoop.sock_recv(sock, nbytes)
   从socket获取数据。仿照的socket.socket.recv()这个阻塞方法。
   返回值是bytes(字节)对象,表明接受的数据。一次接受的字节数的最大值由nbytes参数指定。
SelectorEventLoop事件循环调用这个方法的时候,sock参数必须是非阻塞的socket。
   这个是一个协程方法。

coroutine AbstractEventLoop.sock_sendall(sock, data)
   给socket发送数据。仿照的socket.socket.sendall()这个阻塞方法。
   这个socket必须链接一个远程的socket。这个方法持续的发送来自于data的数据,直到所有发送完毕或者有错误产生。成功时返回None。错误时会引起一个异常,而且此时没有办法肯定多少数据(若是有的话)被成功地由该链接的接收端处理。
SelectorEventLoop事件循环调用这个方法的时候,sock参数必须是非阻塞的socket。
   这个是一个协程方法。

coroutine AbstractEventLoop.sock_connect(sock, address)
   链接到地址为address的远程socket上。仿照的socket.socket.connect()这个阻塞方法。
SelectorEventLoop事件循环调用这个方法的时候,sock参数必须是非阻塞的socket。
   这个是一个协程方法。
改动于3.5.2版本:address参数不必定须要被解析。socket_connect会经过调用socket.inet_pton()来检查address是否被解析了。若是没有,AbstractEventLoop.getaddrinfo()将被用于解析这个address。

coroutine AbstractEventLoop.sock_accept(sock)
   接受一个链接。仿照的socket.socket.accept()这个阻塞方法。
   sock这个参数必须是已绑定到一个地址而且监听链接的socket。返回值是(conn, address)对,conn是一个新socket对象用于在链接上发送和接受数据,address是绑定到socket上的链接的另外一端的地址。
   sock参数必须是非阻塞的socket。
   这个是一个协程方法。

1.10. 解析主机名
coroutine AbstractEventLoop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)
   这是一个协程方法,相似于socket.getaddrinfo(),可是不阻塞。

coroutine AbstractEventLoop.getnameinfo(sockaddr, flags=0)
   这是一个协程方法,相似于socket.getnameinfo(),可是不阻塞。

1.11. 管道链接
Windows上的SelectorEventLoop不支持这些方法。Windows上的ProactorEventLoop支持这些方法。

coroutine AbstractEventLoop.connect_read_pipe(protocol_factory, pipe)
   在事件循环里注册 读管道。
   protocol_factory参数应该是带有Protocol接口的实例对象。pipe参数应该是一个相似文件(file-like)的对象。返回(transport, protocol)对,transport支持ReadTransport的接口。
SelectorEventLoop事件循环调用这个方法的时候,pipe必须是非阻塞模式。
   这个是一个协程方法。

coroutine AbstractEventLoop.connect_write_pipe(protocol_factory, pipe)
   在事件循环里注册 写管道。
   protocol_factory参数应该是带有BaseProtocol接口的实例对象。pipe参数应该是一个相似文件(file-like)的对象。返回(transport, protocol)对,transport支持WriteTransport的接口。
SelectorEventLoop事件循环调用这个方法的时候,pipe必须是非阻塞模式。
   这个是一个协程方法。

能够参考AbstractEventLoop.subprocess_exec()和AbstractEventLoop.subprocess_shell()方法。

1.12. UNIX信号
仅适用于:UNIX。

AbstractEventLoop.add_signal_handler(signum, callback, *args)
   为信号添加一个处理程序。
   若是信号的数值是无效的或者获取不了,会引起ValueError异常。若是设置处理程序时出现问题,会引起RuntimeError异常。
   (可使用functools.partial()来给callback传递参数)

AbstractEventLoop.remove_signal_handler(sig)
   为信号移除处理程序。
   若是信号处理程序被移除,返回True,不然返回False。

能够参考官方文档的signal模块。

1.13. 运行器(Executor)
在Executor(线程池或进程池)里调用函数。默认状况下,事件循环使用着一个线程池运行器(ThreadPoolExecutor)。

coroutine AbstractEventLoop.run_in_executor(executor, func, *args)
   安排func在指定的运行器(executor)里调用。
   executor参数应该是一个Executor实例。若是executor参数为None,就使用默认运行器。
   (可使用functools.partial()来给func传递参数)
   这个是一个协程方法。

AbstractEventLoop.set_default_executor(executor)
   为run_in_executor()函数设置默认运行器。

1.14. 错误处理API
让你定制事件循环里的异常处理。

AbstractEventLoop.set_exception_handler(handler)
   把handler设置为新的事件循环的异常处理程序。
   若是handler为None,就会设置为默认的异常处理程序。
   若是handler是可被调用(callable)对象,他应该匹配(loop, context)做为参数,其中loop是一个活跃的事件循环,context是一个dict对象(具体参考下面的call_exception_handler()方法里的context)。

AbstractEventLoop.get_exception_handler()
   返回异常处理程序,若是使用的是默认的那个就会返回None。
新增于3.5.2版本。

AbstractEventLoop.default_exception_handler(context)
   默认的异常处理程序。
   这个函数在异常发生且没有设置异常处理程序时被调用;也能被本身定制的异常处理程序调用,若是你想推迟默认行为的话。
   context参数和下面的call_exception_handler()里的context意义同样。

AbstractEventLoop.call_exception_handler(context)
   调用当前事件循环的异常处理程序。
   context是一个包含如下关键字做为key的dict(一些新的key可能会在后面介绍):

'message': 错误消息;
'exception'(可选): 异常对象;
'future'(可选): asyncio.Future实例;
'handle'(可选): asyncio.Handle实例;
'protocol'(可选): Protocol(协议)实例;
'transport'(可选): Transport(传输)实例;
'socket'(可选): socket.socket实例。

注意:这个方法不该该被任何事件循环的子类重载。想使用本身定制的异常处理程序,请使用set_exception_handler()方法。
1.15. 调试模式
AbstractEventLoop.get_debug()
   获得事件循环是否调试模式(布尔值)。
   若是环境变量PYTHONASYNCIODEBUG被设置为一个非空的字符串,默认值是True;不然是False。
新增于3.4.2版本。

AbstractEventLoop.set_debug(enabled: bool)
   为事件循环设置调试模式。
新增于3.4.2版本。

能够参考最后一章 使用asyncio开发 的 asyncio的调试模式 章节。

1.16. 服务端(Server)
class asyncio.Server
   监听socket的服务端。
   经过AbstractEventLoop.create_server()方法和start_server()方法来建立对象;不要直接实例化这个类。
close()

      关闭服务:关闭监听的socket而且设置这些socket的属性为None。
      那些表明现有的客户端链接的socket就悬空了。
      服务端以同步方式关闭;使用wait_close()协程方法会等着服务端被关闭。
coroutinewait_close()

      等待close()方法完成。
      这是一个协程方法。
sockets

      服务端正在监听的socket.socket对象的list;若是已经关闭了,会获得None。

1.17. Handle
class asyncio.Handle
   AbstractEventLoop.call_soon()、AbstractEventLoop.call_soon_threadsafe()、AbstractEventLoop.call_later()和AbstractEventLoop.call_at()的返回值,一个回调包装对象。
cancel()
      关闭这个回调。若是这个回调已经关闭了或者已经运行了,这个方法无效。

1.18. 事件循环实例
1.18.1. 使用call_soon()的Hello World
使用call_soon()方法来安排一个回调的实例。这个回调函数显示“Hello World”而后中止事件循环。

import asyncio

def hello_world(loop):
print('Hello World')
loop.stop()

loop = asyncio.get_event_loop()

安排调用hello_world()

loop.call_soon(hello_world, loop)

阻塞调用由loop.stop()中断

loop.run_forever()
loop.close()
也能够查看使用协程的Hello World协程实例。

1.18.2. 使用call_later()显示当前时间
经过回调方式每秒钟显示当前时间的实例。在五秒钟以内,回调使用call_later()方法来安排它本身而后中止事件循环。

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

安排第一次调用display_date()

end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)

阻塞调用由loop.stop()中断

loop.run_forever()
loop.close()
也能够查看使用协程的显示当前时间协程实例。

1.18.3. 监视文件描述符的读取事件
使用add_reader()方法等待直到文件描述符获取了一些数据,而后中止事件循环。

import asyncio
try:
from socket import socketpair
except ImportError:
from asyncio.windows_utils import socketpair

建立一对链接的文件描述符

rsock, wsock = socketpair()
loop = asyncio.get_event_loop()

def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# 咱们完成了:注销文件描述符
loop.remove_reader(rsock)
# 中止事件循环
loop.stop()

注册文件描述符的读事件

loop.add_reader(rsock, reader)

模拟来自网络的数据接收

loop.call_soon(wsock.send, 'abc'.encode())

运行事件循环

loop.run_forever()

咱们完成了:关闭socket和事件循环

rsock.close()
wsock.close()
loop.close()
1.18.4. 为SIGINT和SIGTERM设置信号处理程序
使用add_signal_handler()方法为SIGINT和SIGTERM信号量注册处理程序。

import asyncio
import functools
import os
import signal

def ask_exit(signame):
print("got signal %s: exit" % signame)
loop.stop()

loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
loop.add_signal_handler(getattr(signal, signame),
functools.partial(ask_exit, signame))

print("Event loop running forever, press Ctrl+C to interrupt.") print("pid %s: send SIGINT or SIGTERM to exit." % os.getpid()) try: loop.run_forever() finally: loop.close() 这个例子仅仅工做在UNIX上。

相关文章
相关标签/搜索