关于我
一个有思想的程序猿,终身学习实践者,目前在一个创业团队任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作了一个大概的了解。做为《前文》的补充