策略¶
事件循环策略是各个进程的全局对象 ,它控制事件循环的管理。每个事件循环都有一个默认策略,可以使用策略API更改和定制该策略。
策略定义了“上下文”的概念,每个上下文管理一个单独的事件循环。默认策略将*context*定义为当前线程。
通过使用自定义事件循环策略,可以自定义 get_event_loop()
、 set_event_loop()
和 new_event_loop()
函数的行为。
策略对象应该实现 AbstractEventLoopPolicy
抽象基类中定义的API。
获取和设置策略¶
可以使用下面函数获取和设置当前进程的策略:
-
asyncio.
get_event_loop_policy
()¶ 返回当前进程域的策略。
-
asyncio.
set_event_loop_policy
(policy)¶ 将 policy 设置为当前进程域策略。
如果 policy 设为
None
将恢复默认策略。
策略对象¶
抽象事件循环策略基类定义如下:
-
class
asyncio.
AbstractEventLoopPolicy
¶ 异步策略的抽象基类。
-
get_event_loop
()¶ 为当前上下文获取事件循环。
返回一个实现
AbstractEventLoop
接口的事件循环对象。该方法永远返回
None
。在 3.6 版更改.
-
set_event_loop
(loop)¶ 将当前上下文的事件循环设置为 loop 。
-
new_event_loop
()¶ 创建并返回一个新的事件循环对象。
该方法永远返回
None
。
-
get_child_watcher
()¶ 获取子进程监视器对象。
返回一个实现
AbstractChildWatcher
接口的监视器对象。该函数仅支持Unix。
-
set_child_watcher
(watcher)¶ 将当前子进程监视器设置为 watcher 。
该函数仅支持Unix。
-
asyncio附带下列内置策略:
-
class
asyncio.
DefaultEventLoopPolicy
¶ The default asyncio policy. Uses
SelectorEventLoop
on Unix andProactorEventLoop
on Windows.不需要手动安装默认策略。asyncio已配置成自动使用默认策略。
在 3.8 版更改: On Windows,
ProactorEventLoop
is now used by default.
-
class
asyncio.
WindowsSelectorEventLoopPolicy
¶ An alternative event loop policy that uses the
SelectorEventLoop
event loop implementation.可用性: Windows。
-
class
asyncio.
WindowsProactorEventLoopPolicy
¶ 使用
ProactorEventLoop
事件循环实现的另一种事件循环策略。可用性: Windows。
进程监视器¶
进程监视器允许定制事件循环如何监视Unix子进程。具体来说,事件循环需要知道子进程何时退出。
在asyncio中子进程由 create_subprocess_exec()
和 loop.subprocess_exec()
函数创建。
asyncio defines the AbstractChildWatcher
abstract base class, which child
watchers should implement, and has four different implementations:
ThreadedChildWatcher
(configured to be used by default),
MultiLoopChildWatcher
, SafeChildWatcher
, and
FastChildWatcher
.
请参阅 子进程和线程 部分。
以下两个函数可用于自定义子进程监视器实现,它将被asyncio事件循环使用:
-
asyncio.
get_child_watcher
()¶ 返回当前策略的当前子监视器。
-
asyncio.
set_child_watcher
(watcher)¶ 将当前策略的子监视器设置为 watcher 。watcher 必须实现
AbstractChildWatcher
基类定义的方法。
注解
第三方事件循环实现可能不支持自定义子监视器。对于这样的事件循环,禁止使用 set_child_watcher()
或不起作用。
-
class
asyncio.
AbstractChildWatcher
¶ -
add_child_handler
(pid, callback, *args)¶ 注册一个新的子处理回调函数。
安排
callback(pid, returncode, *args)
在进程的PID与 pid 相等时调用。指定另一个同进程的回调函数替换之前的回调处理函数。回调函数 callback 必须是线程安全。
-
remove_child_handler
(pid)¶ 删除进程PID与 pid 相等的进程的处理函数。
处理函数成功删除时返回
True
,没有删除时返回False
。
-
attach_loop
(loop)¶ 给一个事件循环绑定监视器。
如果监视器之前已绑定另一个事件循环,那么在绑定新循环前会先解绑原来的事件循环。
注意:循环有可能是
None
。
-
is_active
()¶ Return
True
if the watcher is ready to use.Spawning a subprocess with inactive current child watcher raises
RuntimeError
.3.8 新版功能.
-
close
()¶ 关闭监视器。
必须调用这个方法以确保相关资源会被清理。
-
-
class
asyncio.
ThreadedChildWatcher
¶ This implementation starts a new waiting thread for every subprocess spawn.
It works reliably even when the asyncio event loop is run in a non-main OS thread.
There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates), but stating a thread per process requires extra memory.
This watcher is used by default.
3.8 新版功能.
-
class
asyncio.
MultiLoopChildWatcher
¶ This implementation registers a
SIGCHLD
signal handler on instantiation. That can break third-party code that installs a custom handler for SIGCHLD. signal).The watcher avoids disrupting other code spawning processes by polling every process explicitly on a
SIGCHLD
signal.There is no limitation for running subprocesses from different threads once the watcher is installed.
The solution is safe but it has a significant overhead when handling a big number of processes (O(n) each time a
SIGCHLD
is received).3.8 新版功能.
-
class
asyncio.
SafeChildWatcher
¶ This implementation uses active event loop from the main thread to handle
SIGCHLD
signal. If the main thread has no running event loop another thread cannot spawn a subprocess (RuntimeError
is raised).The watcher avoids disrupting other code spawning processes by polling every process explicitly on a
SIGCHLD
signal.This solution is as safe as
MultiLoopChildWatcher
and has the same O(N) complexity but requires a running event loop in the main thread to work.
-
class
asyncio.
FastChildWatcher
¶ 这种实现直接调用
os.waitpid(-1)
来获取所有已结束的进程,可能会中断其它代码洐生进程并等待它们结束。在处理大量子监视器时没有明显的开销( O(1) 每次子监视器结束)。
This solution requires a running event loop in the main thread to work, as
SafeChildWatcher
.
自定义策略¶
要实现一个新的事件循环策略,建议子类化 DefaultEventLoopPolicy
并重写需要定制行为的方法,例如:
class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
def get_event_loop(self):
"""Get the event loop.
This may be None or an instance of EventLoop.
"""
loop = super().get_event_loop()
# Do something with loop ...
return loop
asyncio.set_event_loop_policy(MyEventLoopPolicy())