This document is for an old version of Python that is no longer supported. You should upgrade, and read the Python documentation for the current stable release.

# політики

An event loop policy is a global per-process object that controls the management of the event loop. Each event loop has a default policy, which can be changed and customized using the policy API.

A policy defines the notion of context and manages a separate event loop per context. The default policy defines context to be the current thread.

By using a custom event loop policy, the behavior of `get_event_loop()`, `set_event_loop()`, and `new_event_loop()` functions can be customized.

Об’єкти політики мають реалізовувати API, визначені в `AbstractEventLoopPolicy` абстрактному базовому класі.

## Отримання та налаштування політики

Наступні функції можна використовувати для отримання та налаштування політики для поточного процесу:

`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`

  Стандартна асинхронна політика. Використовує `SelectorEventLoop` в Unix і `ProactorEventLoop` у Windows.

  Немає необхідності встановлювати стандартну політику вручну. asyncio налаштовано на автоматичне використання політики за замовчуванням.

  Змінено в версії 3.8: У Windows `ProactorEventLoop` тепер використовується за замовчуванням.

class `asyncio.``WindowsSelectorEventLoopPolicy`

  Альтернативна політика циклу подій, яка використовує реалізацію циклу подій `SelectorEventLoop`.

  Availability: Windows.

class `asyncio.``WindowsProactorEventLoopPolicy`

  Альтернативна політика циклу подій, яка використовує реалізацію циклу подій `ProactorEventLoop`.

  Availability: Windows.

## Спостерігачі процесів

Спостерігач процесів дозволяє налаштувати те, як цикл подій відстежує дочірні процеси в Unix. Зокрема, цикл подій повинен знати, коли завершився дочірній процес.

В asyncio дочірні процеси створюються за допомогою функцій `create_subprocess_exec()` і `loop.subprocess_exec()`.

asyncio визначає абстрактний базовий клас `AbstractChildWatcher`, який повинні реалізувати дочірні спостерігачі, і має чотири різні реалізації: `ThreadedChildWatcher` (налаштований для використання за замовчуванням), `MultiLoopChildWatcher`, `SafeChildWatcher` і `FastChildWatcher`.

Дивіться також розділ Subprocess and Threads.

Наступні дві функції можна використовувати для налаштування реалізації спостерігача дочірніх процесів, що використовується циклом асинхронних подій:

`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`()

    Повертає `True`, якщо спостерігач готовий до використання.

    Створення підпроцесу з неактивним поточним дочірнім спостерігачем викликає `RuntimeError`.

    Нове в версії 3.8.

  `close`()

    Закрийте спостерігач.

    Цей метод потрібно викликати, щоб переконатися, що базові ресурси очищені.

class `asyncio.``ThreadedChildWatcher`

  Ця реалізація запускає новий потік очікування для кожного породження підпроцесу.

  Він працює надійно, навіть якщо цикл асинхронних подій виконується в неосновному потоці ОС.

  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.

  Цей спостерігач використовується за замовчуванням.

  Нове в версії 3.8.

class `asyncio.``MultiLoopChildWatcher`

  Ця реалізація реєструє обробник сигналу `SIGCHLD` під час створення екземпляра. Це може порушити код третьої сторони, який встановлює спеціальний обробник для сигналу `SIGCHLD`.

  Спостерігач уникає порушення інших процесів створення коду, явно опитуючи кожен процес за сигналом `SIGCHLD`.

  Немає обмежень для запуску підпроцесів з різних потоків після встановлення спостерігача.

  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`

  Ця реалізація використовує активний цикл подій з основного потоку для обробки сигналу `SIGCHLD`. Якщо основний потік не має запущеного циклу подій, інший потік не може породити підпроцес (виникає `RuntimeError`).

  Спостерігач уникає порушення інших процесів створення коду, явно опитуючи кожен процес за сигналом `SIGCHLD`.

  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)`, можливо, порушуючи інші процеси породження коду та чекаючи їх завершення.

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

  Для роботи цього рішення потрібен запущений цикл подій у головному потоці, як `SafeChildWatcher`.

class `asyncio.``PidfdChildWatcher`

  Ця реалізація опитує дескриптори файлів процесу (pidfds) для очікування завершення дочірнього процесу. У деяких відношеннях `PidfdChildWatcher` є реалізацією дочірнього спостерігача «Золотовласка». Він не потребує сигналів чи потоків, не заважає жодним процесам, запущеним поза циклом подій, і масштабується лінійно залежно від кількості підпроцесів, запущених циклом подій. Основним недоліком є те, що pidfds є специфічними для Linux і працюють лише на останніх (5.3+) ядрах.

  Нове в версії 3.9.

## Спеціальна політика

Щоб запровадити нову політику циклу подій, рекомендується створити підклас `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())