Policies
事件循环策略是控制事件循环 Management 的全局每个进程对象。每个事件循环都有一个默认策略,可以使用策略 API 对其进行更改和自定义。
策略定义* context 的概念,并根据上下文 Management 一个单独的事件循环。默认策略将 context *定义为当前线程。
pass使用自定义事件循环策略,可以自定义get_event_loop(),set_event_loop()和new_event_loop()函数的行为。
策略对象应实现AbstractEventLoopPolicy抽象 Base Class 中定义的 API。
获取和设置策略
以下Function可用于获取和设置当前流程的策略:
-
asyncio.
get_event_loop_policy
( )- 返回当前的整个流程范围的 Policy。
-
asyncio.
set_event_loop_policy
(* policy *)- 将当前流程范围的策略设置为* policy *。
如果* policy *设置为None
,则将还原默认策略。
Policy Objects
抽象事件循环策略 Base Class 定义如下:
-
类别
asyncio.
AbstractEventLoopPolicy
- 异步策略的抽象 Base Class。
-
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 *。
此函数特定于 Unix。
asyncio 随附以下内置策略:
- 类别
asyncio.
DefaultEventLoopPolicy
- 默认的异步策略。在 Unix 上使用SelectorEventLoop,在 Windows 上使用ProactorEventLoop。
无需手动安装默认策略。 asyncio 配置为自动使用默认策略。
在版本 3.8 中更改:在 Windows 上,默认情况下现在使用ProactorEventLoop。
- 类别
asyncio.
WindowsSelectorEventLoopPolicy
- 使用SelectorEventLoop事件循环实现的替代事件循环策略。
Availability: Windows.
- 类别
asyncio.
WindowsProactorEventLoopPolicy
- 使用ProactorEventLoop事件循环实现的替代事件循环策略。
Availability: Windows.
Process Watchers
进程监视程序允许自定义事件循环如何监视 Unix 上的子进程。具体来说,事件循环需要知道子进程何时退出。
在异步中,子进程是使用create_subprocess_exec()和loop.subprocess_exec()函数创建的。
asyncio 定义了子观察者应实现的AbstractChildWatcher抽象 Base Class,并具有四个不同的实现:ThreadedChildWatcher(默认配置为使用),MultiLoopChildWatcher,SafeChildWatcher和FastChildWatcher。
另请参见子进程和线程部分。
以下两个函数可用于定制 asyncio 事件循环使用的子进程监视程序实现:
-
asyncio.
get_child_watcher
( )- 返回当前 child 观察者以获取当前策略。
-
asyncio.
set_child_watcher
(观察者)- 将当前策略的当前 child 观察者设置为* watcher *。 观察者必须实现AbstractChildWatcherBase Class 中定义的方法。
Note
第三方事件循环实现可能不支持自定义子观察者。对于此类事件循环,可能禁止使用set_child_watcher()或不起作用。
- 类别
asyncio.
AbstractChildWatcher
-
add_child_handler
(* pid , callback ,* args *)- 注册一个新的子处理程序。
-
PID 等于* pid *的进程终止时,安排要调用callback(pid, returncode, *args)
。为同一进程指定另一个回调将替换先前的处理程序。
- callback *可调用必须是线程安全的。
remove_child_handler
(* pid *)- 删除 PID 等于* pid *的进程的处理程序。
如果成功删除了处理程序,则函数返回True
;如果没有要删除的内容,则返回False
。
attach_loop
(* loop *)- 将观察者附加到事件循环。
如果观察者先前已附加到事件循环,则在附加到新循环之前先将其分离。
注意:循环可能是None
。
is_active
( )- 如果可以使用观察者,则返回
True
。
- 如果可以使用观察者,则返回
用当前非活动的 child 观察者生成子流程会引发RuntimeError。
3.8 版的新Function。
close
( )- 关闭观察者。
必须调用此方法以确保清除基础资源。
- 类别
asyncio.
ThreadedChildWatcher
- 此实现为每个子进程生成一个新的 await 线程。
即使 asyncio 事件循环在非主 OS 线程中运行,它也可以可靠地工作。
处理大量子代时(每次子代终止时为* O(1)*),没有明显的开销,但是为每个进程语句一个线程需要额外的内存。
默认情况下使用此监视程序。
3.8 版的新Function。
- 类别
asyncio.
MultiLoopChildWatcher
- 此实现在实例化时注册一个
SIGCHLD
signal 处理程序。这可能会破坏为 SIGCHLD 安装自定义处理程序的第三方代码。signal)。
- 此实现在实例化时注册一个
监视程序pass在SIGCHLD
signal 上显式轮询每个进程来避免破坏其他代码生成进程。
安装观察程序后,从不同线程运行子流程没有任何限制。
该解决方案是安全的,但是在处理大量进程时(每次接收到SIGCHLD
时,* O(n)*)都会产生很大的开销。
3.8 版的新Function。
- 类别
asyncio.
SafeChildWatcher
- 此实现使用来自主线程的活动事件循环来处理
SIGCHLD
signal。如果主线程没有正在运行的事件循环,则另一个线程无法生成子进程(引发RuntimeError)。
- 此实现使用来自主线程的活动事件循环来处理
监视程序pass在SIGCHLD
signal 上显式轮询每个进程来避免破坏其他代码生成进程。
该解决方案与MultiLoopChildWatcher一样安全,并且具有相同的* O(N)*复杂度,但需要在主线程中运行事件循环才能工作。
- 类别
asyncio.
FastChildWatcher
- 此实现pass直接调用
os.waitpid(-1)
来收获每个终止的进程,从而可能破坏其他代码生成进程并 await 其终止。
- 此实现pass直接调用
处理大量子代时(每次子代终止时为* O(1)*),没有明显的开销。
此解决方案要求主线程中正在运行的事件循环(如SafeChildWatcher)起作用。
Custom Policies
要实施新的事件循环策略,建议子类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())