註冊、執行和關閉延時調用(超時)
爲各類通訊建立客戶端和服務端傳輸
爲一個外部程序通訊啓動子進程和相關的傳輸
把高成本的函數調用委託到線程池
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()
loop.call_soon(hello_world, loop)
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()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
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()
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上。