關於我
一個有思想的程序猿,終身學習實踐者,目前在一個創業團隊任team lead,技術棧涉及Android、Python、Java和Go,這個也是咱們團隊的主要技術棧。
Github:https://github.com/hylinux1024
微信公衆號:終身開發者(angrycode)html
在前文《爲什麼你還不懂得如何使用Python協程
》 中提到協程是經過asyncio
包中的高級API
來啓動的。而asyncio
模塊中的核心就是事件循環(Event Loop
)。它可用於執行異步任務、事件回調、執行網絡IO操做和運行子進程。官方的文檔也是建議開發者應該儘可能使用asyncio
包提供的高級的API
,避免直接使用Event Loop
對象中的方法。python
系統提供的底層能力的功能模塊例如網絡鏈接、文件IO等都會使用到loop
。linux
大多數狀況下,這些高級API
能夠知足衆多使用場景,但做爲一個有追求的猿類,應該要有一點點探索的精神,看看在asyncio
封裝之下的Event Loop
。git
Event Loop
對象asyncio.get_running_loop()
loop
對象asyncio.get_event_loop()
loop
對象。若是當前系統線程尚未loop
對象,那麼就會建立一個新的loop
對象,並使用asyncio.set_event_loop(loop)
方法設置到當前系統線程中。asyncio.new_event_loop()
loop
對象asyncio.set_event_loop(loop)
loop
設置成系統線程使用的對象Event Loop
對象的經常使用方法若是使用相似asyncio.run()
這些高級API
,如下這些方法,基本上不多會用到,建議通讀一下,大概知道loop
對象擁有哪些API
,瞭解如下底層的實現細節。github
loop.run_until_complete(future)
future
對象執行完成才返回loop.run_forever()
loop.stop()
方法loop.stop()
loop
對象loop.is_running()
loop
是否正在運行loop.is_closed()
loop
是否關閉loop.close()
loop
對象coroutine loop.shutdown_asyncgens()
try: loop.run_forever() finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()
loop.call_soon(callback, *args, context=None)
callback
方法,args
是方法中的參數loop.call_soon_threadsafe(callback, *args, context=None)
call_soon()
iimport asyncio import time def hello_world(loop): print('Hello World') time.sleep(3) # 模擬長時間操做 loop.stop() loop = asyncio.get_event_loop() # 使用loop執行 hello_world() loop.call_soon(hello_world, loop) # 會一直阻塞,直到調用了stop方法 try: loop.run_forever() finally: loop.close()
可設置延遲執行的方法windows
loop.call_later(delay, callback, *args, context=None)
delay
秒後執行loop.call_at(when, callback, *args, context=None)
loop.time()
import asyncio import datetime def display_date(end_time, loop): print(datetime.datetime.now()) if (loop.time() + 1.0) < end_time: # 1秒後執行 loop.call_later(1, display_date, end_time, loop) else: loop.stop() loop = asyncio.get_event_loop() # 執行5秒 end_time = loop.time() + 5.0 loop.call_soon(display_date, end_time, loop) # 一直運行,等待stop的調用 try: loop.run_forever() finally: loop.close()
執行結果打印5秒時間點安全
2019-05-09 22:34:47.885412 2019-05-09 22:34:48.887513 2019-05-09 22:34:49.889396 2019-05-09 22:34:50.894316 2019-05-09 22:34:51.898457
loop.create_future()
future
對象loop.create_task(coro)
coro
放入調度,並返回task
對象loop.set_task_factory(factory)
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
等參數建立網絡鏈接微信
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)
建立UDP
鏈接網絡
coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None)
建立Unix
鏈接異步
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
服務
coroutine loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)
建立Unix
服務
coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None)
封裝已創建的鏈接,返回元組(transport, protocol)
asyncio
的事件循環有兩種不一樣的實現:SelectorEventLoop
和 ProactorEventLoop
,它們的父類是AbstractEventLoop
SelectorEventLoop
這個是asyncio
默認使用的Event Loop
實現,支持unix
和windows
平臺
import asyncio import selectors selector = selectors.SelectSelector() loop = asyncio.SelectorEventLoop(selector) asyncio.set_event_loop(loop)
ProactorEventLoop
這個是Windows
平臺專有的實現
import asyncio import sys if sys.platform == 'win32': loop = asyncio.ProactorEventLoop() asyncio.set_event_loop(loop)
事件循環是asyncio
的核心,asncio
模塊的不少高級接口是經過封裝Event Loop
對象來實現的。它提供了執行異步任務、事件回調、執行網絡IO操做和運行子進程的能力。
本文是經過官方文檔對事件循環的概念和它的常見API作了一個大概的瞭解。做爲《前文》的補充