内容简介:在前文系统提供的底层能力的功能模块例如网络连接、文件IO等都会使用到大多数情况下,这些高级
在前文 《为何你还不懂得如何使用 Python 协程
》
中提到协程是通过 asyncio
包中的高级 API
来启动的。而 asyncio
模块中的核心就是事件循环( Event Loop
)。它可用于执行异步任务、事件回调、执行网络IO操作和运行子进程。官方的文档也是建议开发者应该尽量使用 asyncio
包提供的高级的 API
,避免直接使用 Event Loop
对象中的方法。
系统提供的底层能力的功能模块例如网络连接、文件IO等都会使用到 loop
。
大多数情况下,这些高级 API
可以满足众多使用场景,但作为一个有追求的猿类,应该要有一点点探索的精神,看看在 asyncio
封装之下的 Event Loop
。
获取 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
,了解以下底层的实现细节。
启动和停止
-
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()
复制代码
可延迟的回调方法
可设置延迟执行的方法
-
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 复制代码
创建Future和Tasks
-
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)
Event Loop 的实现
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)
复制代码
0x01 总结
事件循环是 asyncio
的核心, asncio
模块的很多高级接口是通过封装 Event Loop
对象来实现的。它提供了执行异步任务、事件回调、执行网络IO操作和运行子进程的能力。
本文是通过官方文档对事件循环的概念和它的常见API做了一个大概的了解。作为《前文》的补充
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 了解Vert.x:事件循环
- 深入了解nodejs的事件循环机制
- 深入了解JavaScript 中的For循环之详解
- 从event loop到async await来了解事件循环机制
- 深入了解Flutter的isolate(1) ---- 事件循环(event loop)及代码运行顺序
- 008.Python循环for循环
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Practical JavaScript, DOM Scripting and Ajax Projects
Frank Zammetti / Apress / April 16, 2007 / $44.99
http://www.amazon.com/exec/obidos/tg/detail/-/1590598164/ Book Description Practical JavaScript, DOM, and Ajax Projects is ideal for web developers already experienced in JavaScript who want to ......一起来看看 《Practical JavaScript, DOM Scripting and Ajax Projects》 这本书的介绍吧!