> **Источник:** https://python-all.ru/3.7/library/asyncio-policy.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# Политики

Политика цикла событий – это глобальный для каждого процесса объект, управляющий циклом событий. Каждый цикл событий имеет политику по умолчанию, которую можно изменить и настроить с помощью API политик.

Политика определяет понятие *контекста* и управляет отдельным циклом событий для каждого контекста. Политика по умолчанию определяет *контекст* как текущий поток.

Используя собственную политику цикла событий, можно настроить поведение функций [`get_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_event_loop), [`set_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.set_event_loop) и [`new_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.new_event_loop).

Объекты политик должны реализовывать API, определённые в абстрактном базовом классе [`AbstractEventLoopPolicy`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractEventLoopPolicy).

## Получение и установка политики

Следующие функции можно использовать для получения и установки политики для текущего процесса:

#### `asyncio.get_event_loop_policy()`

Возвращает текущую политику для всего процесса.

#### `asyncio.set_event_loop_policy(policy)`

Устанавливает текущую политику для всего процесса в *policy*.

Если для *policy* установлено значение `None`, восстанавливается стандартная политика.

## Объекты политик

Абстрактный базовый класс политики цикла событий определяется следующим образом:

#### `class asyncio.AbstractEventLoopPolicy`

Абстрактный базовый класс для политик asyncio.

#### `get_event_loop()`

Возвращает цикл событий для текущего контекста.

Возвращает объект цикла событий, реализующий интерфейс [`AbstractEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.AbstractEventLoop).

Этот метод никогда не должен возвращать `None`.

Изменено в версии 3.6.

#### `set_event_loop(loop)`

Устанавливает цикл событий для текущего контекста равным *loop*.

#### `new_event_loop()`

Создаёт и возвращает новый объект цикла событий.

Этот метод никогда не должен возвращать `None`.

#### `get_child_watcher()`

Получить объект наблюдателя за дочерними процессами.

Возвращает объект наблюдателя, реализующий [`AbstractChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractChildWatcher) интерфейс.

Эта функция специфична для Unix.

#### `set_child_watcher(watcher)`

Устанавливает текущий наблюдатель за дочерними процессами на *watcher*.

Эта функция специфична для Unix.

asyncio включает следующие встроенные политики:

#### `class asyncio.DefaultEventLoopPolicy`

Политика asyncio по умолчанию. Использует [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) как на Unix, так и на Windows.

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

#### `class asyncio.WindowsProactorEventLoopPolicy`

Альтернативная политика цикла событий, использующая реализацию цикла событий [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).

[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Windows.

## Наблюдатели за процессами

Наблюдатель за процессами позволяет настраивать, как цикл событий отслеживает дочерние процессы в Unix. В частности, циклу событий необходимо знать, когда дочерний процесс завершился.

В asyncio дочерние процессы создаются с помощью функций [`create_subprocess_exec()`](https://python-all.ru/3.7/library/asyncio-subprocess.html#asyncio.create_subprocess_exec) и [`loop.subprocess_exec()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec).

asyncio определяет абстрактный базовый класс [`AbstractChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractChildWatcher), который должны реализовывать наблюдатели за дочерними процессами, и имеет две различные реализации: [`SafeChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.SafeChildWatcher) (настроена для использования по умолчанию) и [`FastChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.FastChildWatcher).

См. также раздел [Подпроцессы и потоки](https://python-all.ru/3.7/library/asyncio-subprocess.html#asyncio-subprocess-threads) .

Следующие две функции можно использовать для настройки реализации наблюдателя за дочерними процессами, используемого циклом событий asyncio:

#### `asyncio.get_child_watcher()`

Возвращает текущий наблюдатель за дочерними процессами для текущей политики.

#### `asyncio.set_child_watcher(watcher)`

Устанавливает текущий наблюдатель за дочерними процессами на *watcher* для текущей политики. *watcher* должен реализовывать методы, определённые в базовом классе [`AbstractChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractChildWatcher).

> **Примечание**
>
> Реализации циклов событий от сторонних разработчиков могут не поддерживать пользовательские наблюдатели за дочерними процессами. Для таких циклов событий использование [`set_child_watcher()`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.set_child_watcher) может быть запрещено или не иметь эффекта.

#### `class asyncio.AbstractChildWatcher`

#### `add_child_handler(pid, callback, *args)`

Регистрирует новый обработчик дочернего процесса.

Организует вызов `callback(pid, returncode, *args)` при завершении процесса с PID, равным *pid*. Указание другого колбэка для того же процесса заменяет предыдущий обработчик.

Вызываемый объект *колбэк* должен быть потокобезопасным.

#### `remove_child_handler(pid)`

Удаляет обработчик для процесса с PID, равным *pid*.

Функция возвращает `True`, если обработчик был успешно удалён, и `False`, если удалять было нечего.

#### `attach_loop(loop)`

Присоединяет наблюдатель к циклу событий.

Если наблюдатель ранее был присоединён к циклу событий, то перед присоединением к новому циклу он сначала отсоединяется.

Примечание: loop может быть `None`.

#### `close()`

Закрывает наблюдатель.

Этот метод необходимо вызвать, чтобы гарантировать очистку нижележащих ресурсов.

#### `class asyncio.SafeChildWatcher`

Эта реализация предотвращает нарушение работы другого кода, порождающего процессы, за счет явного опроса каждого процесса по сигналу `SIGCHLD`.

Это безопасное решение, но оно создает значительные накладные расходы при обработке большого количества процессов (*O(n)* каждый раз при получении `SIGCHLD`).

asyncio использует эту безопасную реализацию по умолчанию.

#### `class asyncio.FastChildWatcher`

Эта реализация собирает каждый завершённый процесс, напрямую вызывая `os.waitpid(-1)`, что потенциально нарушает работу другого кода, запускающего процессы и ожидающего их завершения.

Нет заметных накладных расходов при обработке большого количества дочерних процессов (*O(1)* каждый раз при завершении дочернего процесса).

## Пользовательские политики

Для реализации новой политики цикла событий рекомендуется создать подкласс [`DefaultEventLoopPolicy`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.DefaultEventLoopPolicy) и переопределить методы, для которых требуется особое поведение, например:

```python
class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):

    def get_event_loop(self):
        """Получить цикл событий.

        Это может быть None или экземпляр EventLoop.
        """
        loop = super().get_event_loop()
        # Сделать что-то с циклом ...
        return loop

asyncio.set_event_loop_policy(MyEventLoopPolicy())
```
