# 策略

事件循环策略是各个进程的全局对象 ，它控制事件循环的管理。每个事件循环都有一个默认策略，可以使用策略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 and `ProactorEventLoop` 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())