策略

事件循环策略是一个用于获取和设置当前 事件循环 的全局对象,还可以创建新的事件循环。 默认策略可以可以被 替换内置替代策略 以使用不同的事件循环实现,或者替换为可以覆盖这些行为的 自定义策略

策略对象 可为每个 context 获取和设置单独的事件循环。 在默认情况下是分线程,不过自定义策略可以按不同的方式定义 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()

Get a child process watcher object.

Return a watcher object implementing the AbstractChildWatcher interface.

This function is Unix specific.

自 3.12 版本弃用.

set_child_watcher(watcher)

Set the current child process watcher to watcher.

This function is Unix specific.

自 3.12 版本弃用.

asyncio附带下列内置策略:

class asyncio.DefaultEventLoopPolicy

默认的 asyncio 策略。 在 Unix 上使用 SelectorEventLoop 而在 Windows 上使用 ProactorEventLoop

不需要手动安装默认策略。asyncio已配置成自动使用默认策略。

在 3.8 版本发生变更: 在 Windows 上,现在默认会使用 ProactorEventLoop

自 3.12 版本弃用: The get_event_loop() method of the default asyncio policy now emits a DeprecationWarning if there is no current event loop set and it decides to create one. In some future Python release this will become an error.

class asyncio.WindowsSelectorEventLoopPolicy

一个使用 SelectorEventLoop 事件循环实现的替代事件循环策略。

Availability: Windows.

class asyncio.WindowsProactorEventLoopPolicy

使用 ProactorEventLoop 事件循环实现的另一种事件循环策略。

Availability: Windows.

Process Watchers

A process watcher allows customization of how an event loop monitors child processes on Unix. Specifically, the event loop needs to know when a child process has exited.

In asyncio, child processes are created with create_subprocess_exec() and loop.subprocess_exec() functions.

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.

See also the Subprocess and Threads section.

The following two functions can be used to customize the child process watcher implementation used by the asyncio event loop:

asyncio.get_child_watcher()

Return the current child watcher for the current policy.

自 3.12 版本弃用.

asyncio.set_child_watcher(watcher)

Set the current child watcher to watcher for the current policy. watcher must implement methods defined in the AbstractChildWatcher base class.

自 3.12 版本弃用.

备注

Third-party event loops implementations might not support custom child watchers. For such event loops, using set_child_watcher() might be prohibited or have no effect.

class asyncio.AbstractChildWatcher
add_child_handler(pid, callback, *args)

Register a new child handler.

Arrange for callback(pid, returncode, *args) to be called when a process with PID equal to pid terminates. Specifying another callback for the same process replaces the previous handler.

The callback callable must be thread-safe.

remove_child_handler(pid)

Removes the handler for process with PID equal to pid.

The function returns True if the handler was successfully removed, False if there was nothing to remove.

attach_loop(loop)

Attach the watcher to an event loop.

If the watcher was previously attached to an event loop, then it is first detached before attaching to the new loop.

Note: loop may be None.

is_active()

Return True if the watcher is ready to use.

Spawning a subprocess with inactive current child watcher raises RuntimeError.

Added in version 3.8.

close()

Close the watcher.

This method has to be called to ensure that underlying resources are cleaned-up.

自 3.12 版本弃用.

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 starting a thread per process requires extra memory.

This watcher is used by default.

Added in version 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).

Added in version 3.8.

自 3.12 版本弃用.

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.

自 3.12 版本弃用.

class asyncio.FastChildWatcher

This implementation reaps every terminated processes by calling os.waitpid(-1) directly, possibly breaking other code spawning processes and waiting for their termination.

There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates).

This solution requires a running event loop in the main thread to work, as SafeChildWatcher.

自 3.12 版本弃用.

class asyncio.PidfdChildWatcher

This implementation polls process file descriptors (pidfds) to await child process termination. In some respects, PidfdChildWatcher is a "Goldilocks" child watcher implementation. It doesn't require signals or threads, doesn't interfere with any processes launched outside the event loop, and scales linearly with the number of subprocesses launched by the event loop. The main disadvantage is that pidfds are specific to Linux, and only work on recent (5.3+) kernels.

Added in version 3.9.

自定义策略

要实现一个新的事件循环策略,建议子类化 DefaultEventLoopPolicy 并重写需要定制行为的方法,例如:

class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):

    def get_event_loop(self):
        """获取事件循环。

        这可能为 None 或是一个 EventLoop 的实例。
        """
        loop = super().get_event_loop()
        # 对 loop 执行一些操作 ...
        return loop

asyncio.set_event_loop_policy(MyEventLoopPolicy())