18.5.2. 事件循环¶
18.5.2.1. 事件循环函数¶
下面的函数是访问全局策略方法的便利快捷方式。注意这只是提供了对默认策略的访问,除非要在进程开始之前设置替代的策略。
-
asyncio.
get_event_loop
()¶ 与调用
get_event_loop_policy().get_event_loop()
等价。
-
asyncio.
set_event_loop
(loop)¶ 等价于调用
get_event_loop_policy().set_event_loop(loop)
。
-
asyncio.
new_event_loop
()¶ 等价于调用
get_event_loop_policy().new_event_loop()
。
18.5.2.2. 可用的事件循环¶
asyncio当前提供两种事件循环实现: SelectorEventLoop
和 ProactorEventLoop
。
-
class
asyncio.
SelectorEventLoop
¶ 基于
selectors
模块的事件循环。AbstractEventLoop
的子类。使用对应平台上最高效的选择器。
在Windows上,只支持套接字(举例:不支持管线):参见 MSDN关于select的文档 <https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx> _ 。
-
class
asyncio.
ProactorEventLoop
¶ Windows上的 Proactor 事件循环,使用的是 “I/O 完成端口”,也叫做 IOCP。为
AbstractEventLoop
的子类。可用性:Windows。
参见
在Windows上使用 ProactorEventLoop
的例子:
import asyncio, sys
if sys.platform == 'win32':
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
18.5.2.3. 平台支持¶
asyncio
模块被设计为可移植的,但是每个平台仍旧有细微的不同,而且不一定支持 asyncio
的所有特性。
18.5.2.3.1. Windows¶
Windows事件循环的一般限制:
- 不支持
create_unix_connection()
和create_unix_server()
:socket.AF_UNIX
套接字族只在UNIX上可用 - 不支持
add_signal_handler()
和remove_signal_handler()
- 不支持
EventLoopPolicy.set_child_watcher()
。ProactorEventLoop
支持子进程。监控子进程的实现只有一种,不需要对其进行设置。
特定于 SelectorEventLoop
的限制:
SelectSelector
只被用于支持套接字,并且最多支持512个套接字。add_reader()
和add_writer()
只接受套接字的文件描述符- 不支持管线(示例:
connect_read_pipe()
,connect_write_pipe()
) - 不支持 Subprocesses (示例:
subprocess_exec()
,subprocess_shell()
)
特定于 ProactorEventLoop
的限制:
- 不支持
create_datagram_endpoint()
(UDP) - 不支持
add_reader()
和add_writer()
Windows上单调时钟的分辨率大约为 15.6 毫秒。最佳的分辨率是 0.5 毫秒。分辨率依赖于具体的硬件(HPET 的可用性)和Windows的设置。参见:ref:asyncio delayed calls <asyncio-delayed-calls> 。
在 3.5 版更改: ProactorEventLoop
现在支持SSL了。
18.5.2.3.2. Mac OS X¶
类似于PTY的字符设备在Mavericks (Mac OS 10.9)之前并未有很好的支持。在 Mac OS 10.5以及更老的版本上则根本不支持。
在Mac OS 10.6、10.7和10.8上,默认的事件循环是 SelectorEventLoop
,其使用了 selectors.KqueueSelector
。 selectors.KqueueSelector
在这些版本上并不支持字符设备。SelectorEventLoop
可以同 SelectSelector
或者 PollSelector
一同使用来在这些版本的Mac OS X上支持块设备。 例如:
import asyncio
import selectors
selector = selectors.SelectSelector()
loop = asyncio.SelectorEventLoop(selector)
asyncio.set_event_loop(loop)
18.5.2.4. 事件循环策略和默认策略¶
使用一个 策略 模式对事件循环进行管理,用以为特定平台和框架提供最大限度的灵活性。在一个进程的执行中,唯一的全局策略对象,基于调用的上下文,管理着此进程所有可用的事件循环。一个策略就是一个实现了 AbstractEventLoopPolicy
的对象。
For most users of asyncio
, policies never have to be dealt with
explicitly, since the default global policy is sufficient.
The default policy defines context as the current thread, and manages an event
loop per thread that interacts with asyncio
. The module-level functions
get_event_loop()
and set_event_loop()
provide convenient access to
event loops managed by the default policy.
18.5.2.5. 事件循环策略接口¶
一个事件循环必须实现如下的接口:
-
class
asyncio.
AbstractEventLoopPolicy
¶ 事件循环策略。
-
get_event_loop
()¶ 为当前上下文获取事件循环。
Returns an event loop object implementing the
AbstractEventLoop
interface.如果没有为当前上下文设置一个事件循环,并且当前策略不能创建一个事件循环,就会抛出一个错误。其务必不能返回
None
。
-
set_event_loop
(loop)¶ 将当前上下文的事件循环设置为 loop 。
-
new_event_loop
()¶ 根据策略的规则,创建并返回一个新的事件循环对象。
如果有需要设置这个循环作为当前上下文的事件循环,就必须显式调用
set_event_loop()
。
-