asyncio-policy.md
1> **Источник:** https://python-all.ru/3.7/library/asyncio-policy.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Политики89Политика цикла событий – это глобальный для каждого процесса объект, управляющий циклом событий. Каждый цикл событий имеет политику по умолчанию, которую можно изменить и настроить с помощью API политик.1011Политика определяет понятие *контекста* и управляет отдельным циклом событий для каждого контекста. Политика по умолчанию определяет *контекст* как текущий поток.1213Используя собственную политику цикла событий, можно настроить поведение функций [`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).1415Объекты политик должны реализовывать API, определённые в абстрактном базовом классе [`AbstractEventLoopPolicy`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractEventLoopPolicy).1617## Получение и установка политики1819Следующие функции можно использовать для получения и установки политики для текущего процесса:2021#### `asyncio.get_event_loop_policy()`2223Возвращает текущую политику для всего процесса.2425#### `asyncio.set_event_loop_policy(policy)`2627Устанавливает текущую политику для всего процесса в *policy*.2829Если для *policy* установлено значение `None`, восстанавливается стандартная политика.3031## Объекты политик3233Абстрактный базовый класс политики цикла событий определяется следующим образом:3435#### `class asyncio.AbstractEventLoopPolicy`3637Абстрактный базовый класс для политик asyncio.3839#### `get_event_loop()`4041Возвращает цикл событий для текущего контекста.4243Возвращает объект цикла событий, реализующий интерфейс [`AbstractEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.AbstractEventLoop).4445Этот метод никогда не должен возвращать `None`.4647Изменено в версии 3.6.4849#### `set_event_loop(loop)`5051Устанавливает цикл событий для текущего контекста равным *loop*.5253#### `new_event_loop()`5455Создаёт и возвращает новый объект цикла событий.5657Этот метод никогда не должен возвращать `None`.5859#### `get_child_watcher()`6061Получить объект наблюдателя за дочерними процессами.6263Возвращает объект наблюдателя, реализующий [`AbstractChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractChildWatcher) интерфейс.6465Эта функция специфична для Unix.6667#### `set_child_watcher(watcher)`6869Устанавливает текущий наблюдатель за дочерними процессами на *watcher*.7071Эта функция специфична для Unix.7273asyncio включает следующие встроенные политики:7475#### `class asyncio.DefaultEventLoopPolicy`7677Политика asyncio по умолчанию. Использует [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) как на Unix, так и на Windows.7879Нет необходимости устанавливать политику по умолчанию вручную. asyncio настроена на автоматическое использование политики по умолчанию.8081#### `class asyncio.WindowsProactorEventLoopPolicy`8283Альтернативная политика цикла событий, использующая реализацию цикла событий [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).8485[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Windows.8687## Наблюдатели за процессами8889Наблюдатель за процессами позволяет настраивать, как цикл событий отслеживает дочерние процессы в Unix. В частности, циклу событий необходимо знать, когда дочерний процесс завершился.9091В 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).9293asyncio определяет абстрактный базовый класс [`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).9495См. также раздел [Подпроцессы и потоки](https://python-all.ru/3.7/library/asyncio-subprocess.html#asyncio-subprocess-threads) .9697Следующие две функции можно использовать для настройки реализации наблюдателя за дочерними процессами, используемого циклом событий asyncio:9899#### `asyncio.get_child_watcher()`100101Возвращает текущий наблюдатель за дочерними процессами для текущей политики.102103#### `asyncio.set_child_watcher(watcher)`104105Устанавливает текущий наблюдатель за дочерними процессами на *watcher* для текущей политики. *watcher* должен реализовывать методы, определённые в базовом классе [`AbstractChildWatcher`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.AbstractChildWatcher).106107> **Примечание**108>109> Реализации циклов событий от сторонних разработчиков могут не поддерживать пользовательские наблюдатели за дочерними процессами. Для таких циклов событий использование [`set_child_watcher()`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.set_child_watcher) может быть запрещено или не иметь эффекта.110111#### `class asyncio.AbstractChildWatcher`112113#### `add_child_handler(pid, callback, *args)`114115Регистрирует новый обработчик дочернего процесса.116117Организует вызов `callback(pid, returncode, *args)` при завершении процесса с PID, равным *pid*. Указание другого колбэка для того же процесса заменяет предыдущий обработчик.118119Вызываемый объект *колбэк* должен быть потокобезопасным.120121#### `remove_child_handler(pid)`122123Удаляет обработчик для процесса с PID, равным *pid*.124125Функция возвращает `True`, если обработчик был успешно удалён, и `False`, если удалять было нечего.126127#### `attach_loop(loop)`128129Присоединяет наблюдатель к циклу событий.130131Если наблюдатель ранее был присоединён к циклу событий, то перед присоединением к новому циклу он сначала отсоединяется.132133Примечание: loop может быть `None`.134135#### `close()`136137Закрывает наблюдатель.138139Этот метод необходимо вызвать, чтобы гарантировать очистку нижележащих ресурсов.140141#### `class asyncio.SafeChildWatcher`142143Эта реализация предотвращает нарушение работы другого кода, порождающего процессы, за счет явного опроса каждого процесса по сигналу `SIGCHLD`.144145Это безопасное решение, но оно создает значительные накладные расходы при обработке большого количества процессов (*O(n)* каждый раз при получении `SIGCHLD`).146147asyncio использует эту безопасную реализацию по умолчанию.148149#### `class asyncio.FastChildWatcher`150151Эта реализация собирает каждый завершённый процесс, напрямую вызывая `os.waitpid(-1)`, что потенциально нарушает работу другого кода, запускающего процессы и ожидающего их завершения.152153Нет заметных накладных расходов при обработке большого количества дочерних процессов (*O(1)* каждый раз при завершении дочернего процесса).154155## Пользовательские политики156157Для реализации новой политики цикла событий рекомендуется создать подкласс [`DefaultEventLoopPolicy`](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio.DefaultEventLoopPolicy) и переопределить методы, для которых требуется особое поведение, например:158159```python160class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):161162 def get_event_loop(self):163 """Получить цикл событий.164165 Это может быть None или экземпляр EventLoop.166 """167 loop = super().get_event_loop()168 # Сделать что-то с циклом ...169 return loop170171asyncio.set_event_loop_policy(MyEventLoopPolicy())172```173