asyncio-policy.md
1> **Источник:** https://python-all.ru/3.9/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.9/library/asyncio-eventloop.html#asyncio.get_event_loop), [`set_event_loop()`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.set_event_loop) и [`new_event_loop()`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.new_event_loop).1415Объекты политик должны реализовывать API, определённые в абстрактном базовом классе [`AbstractEventLoopPolicy`](https://python-all.ru/3.9/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.9/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.9/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.9/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) в Unix и [`ProactorEventLoop`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) в Windows.7879Нет необходимости устанавливать политику по умолчанию вручную. asyncio настроена на автоматическое использование политики по умолчанию.8081Изменено в версии 3.8: В Windows [`ProactorEventLoop`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) теперь используется по умолчанию.8283#### `class asyncio.WindowsSelectorEventLoopPolicy`8485Альтернативная политика цикла событий, использующая реализацию цикла событий [`SelectorEventLoop`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.SelectorEventLoop).8687[Доступность](https://python-all.ru/3.9/library/intro.html#availability): Windows.8889#### `class asyncio.WindowsProactorEventLoopPolicy`9091Альтернативная политика цикла событий, использующая реализацию цикла событий [`ProactorEventLoop`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).9293[Доступность](https://python-all.ru/3.9/library/intro.html#availability): Windows.9495## Наблюдатели за процессами9697Наблюдатель за процессами позволяет настраивать, как цикл событий отслеживает дочерние процессы в Unix. В частности, циклу событий необходимо знать, когда дочерний процесс завершился.9899В asyncio дочерние процессы создаются с помощью функций [`create_subprocess_exec()`](https://python-all.ru/3.9/library/asyncio-subprocess.html#asyncio.create_subprocess_exec) и [`loop.subprocess_exec()`](https://python-all.ru/3.9/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec).100101asyncio определяет абстрактный базовый класс [`AbstractChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.AbstractChildWatcher), который должны реализовывать наблюдатели за дочерними процессами, и имеет четыре реализации: [`ThreadedChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.ThreadedChildWatcher) (используется по умолчанию), [`MultiLoopChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.MultiLoopChildWatcher), [`SafeChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.SafeChildWatcher) и [`FastChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.FastChildWatcher).102103См. также раздел [Подпроцессы и потоки](https://python-all.ru/3.9/library/asyncio-subprocess.html#asyncio-subprocess-threads) .104105Следующие две функции можно использовать для настройки реализации наблюдателя за дочерними процессами, используемого циклом событий asyncio:106107#### `asyncio.get_child_watcher()`108109Возвращает текущий наблюдатель за дочерними процессами для текущей политики.110111#### `asyncio.set_child_watcher(watcher)`112113Устанавливает текущий наблюдатель за дочерними процессами на *watcher* для текущей политики. *watcher* должен реализовывать методы, определённые в базовом классе [`AbstractChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.AbstractChildWatcher).114115> **Примечание**116>117> Реализации циклов событий от сторонних разработчиков могут не поддерживать пользовательские наблюдатели за дочерними процессами. Для таких циклов событий использование [`set_child_watcher()`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.set_child_watcher) может быть запрещено или не иметь эффекта.118119#### `class asyncio.AbstractChildWatcher`120121#### `add_child_handler(pid, callback, *args)`122123Регистрирует новый обработчик дочернего процесса.124125Организует вызов `callback(pid, returncode, *args)` при завершении процесса с PID, равным *pid*. Указание другого колбэка для того же процесса заменяет предыдущий обработчик.126127Вызываемый объект *колбэк* должен быть потокобезопасным.128129#### `remove_child_handler(pid)`130131Удаляет обработчик для процесса с PID, равным *pid*.132133Функция возвращает `True`, если обработчик был успешно удалён, и `False`, если удалять было нечего.134135#### `attach_loop(loop)`136137Присоединяет наблюдатель к циклу событий.138139Если наблюдатель ранее был присоединён к циклу событий, то перед присоединением к новому циклу он сначала отсоединяется.140141Примечание: loop может быть `None`.142143#### `is_active()`144145Возвращает `True`, если наблюдатель готов к использованию.146147Запуск подпроцесса с *неактивным* текущим наблюдателем дочерних процессов вызывает [`RuntimeError`](https://python-all.ru/3.9/library/exceptions.html#RuntimeError).148149Новое в версии 3.8.150151#### `close()`152153Закрывает наблюдатель.154155Этот метод необходимо вызвать, чтобы гарантировать очистку нижележащих ресурсов.156157#### `class asyncio.ThreadedChildWatcher`158159Эта реализация запускает новый ожидающий поток для каждого запущенного подпроцесса.160161Она работает надёжно, даже если цикл событий asyncio выполняется не в главном потоке ОС.162163Нет заметных накладных расходов при обработке большого количества дочерних процессов (*O(1)* каждый раз при завершении дочернего процесса), но запуск потока на каждый процесс требует дополнительной памяти.164165Этот наблюдатель используется по умолчанию.166167Новое в версии 3.8.168169#### `class asyncio.MultiLoopChildWatcher`170171Эта реализация регистрирует обработчик сигнала `SIGCHLD` при создании экземпляра. Это может нарушить работу стороннего кода, который устанавливает собственный обработчик сигнала `SIGCHLD`.172173Наблюдатель не нарушает работу другого кода, запускающего процессы, благодаря явному опросу каждого процесса при получении сигнала `SIGCHLD`.174175После установки наблюдателя нет ограничений на запуск подпроцессов из разных потоков.176177Решение безопасно, но имеет значительные накладные расходы при обработке большого количества процессов (*O(n)* каждый раз при получении `SIGCHLD`).178179Новое в версии 3.8.180181#### `class asyncio.SafeChildWatcher`182183Эта реализация использует активный цикл событий из главного потока для обработки сигнала `SIGCHLD`. Если в главном потоке нет работающего цикла событий, другой поток не может запустить подпроцесс (возникает [`RuntimeError`](https://python-all.ru/3.9/library/exceptions.html#RuntimeError)).184185Наблюдатель не нарушает работу другого кода, запускающего процессы, благодаря явному опросу каждого процесса при получении сигнала `SIGCHLD`.186187Это решение так же безопасно, как [`MultiLoopChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.MultiLoopChildWatcher), и имеет ту же сложность *O(N)*, но для работы требует работающего цикла событий в главном потоке.188189#### `class asyncio.FastChildWatcher`190191Эта реализация собирает каждый завершённый процесс, напрямую вызывая `os.waitpid(-1)`, что потенциально нарушает работу другого кода, запускающего процессы и ожидающего их завершения.192193Нет заметных накладных расходов при обработке большого количества дочерних процессов (*O(1)* каждый раз при завершении дочернего процесса).194195Это решение требует работающего цикла событий в главном потоке, как и [`SafeChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.SafeChildWatcher).196197#### `class asyncio.PidfdChildWatcher`198199Данная реализация опрашивает файловые дескрипторы процессов (pidfds) для ожидания завершения дочернего процесса. В некотором смысле [`PidfdChildWatcher`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.PidfdChildWatcher) – это реализация наблюдателя за дочерними процессами «Златовласка». Она не требует сигналов или потоков, не мешает процессам, запущенным вне цикла событий, и масштабируется линейно от количества подпроцессов, запущенных циклом событий. Основной недостаток в том, что pidfds специфичны для Linux и работают только на современных (5.3+) ядрах.200201Новое в версии 3.9.202203## Пользовательские политики204205Для реализации новой политики цикла событий рекомендуется создать подкласс [`DefaultEventLoopPolicy`](https://python-all.ru/3.9/library/asyncio-policy.html#asyncio.DefaultEventLoopPolicy) и переопределить методы, для которых требуется особое поведение, например:206207```python208class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):209210 def get_event_loop(self):211 """Получить цикл событий.212213 Это может быть None или экземпляр EventLoop.214 """215 loop = super().get_event_loop()216 # Сделать что-то с циклом ...217 return loop218219asyncio.set_event_loop_policy(MyEventLoopPolicy())220```221