Полисы¶
Политика цикла обработки событий - это глобальный объект, используемый для получения и установки текущего значения event loop, а также для создания новых циклов обработки событий. Политика по умолчанию может быть replaced с built-in alternatives для использования различных реализаций цикла обработки событий или заменена custom policy, которая может переопределять эти варианты поведения.
policy object получает и устанавливает отдельный цикл обработки событий для каждого контекста. По умолчанию это для каждого потока, хотя пользовательские политики могут определять контекст по-разному.
Пользовательские политики цикла обработки событий могут управлять поведением get_event_loop()
, set_event_loop()
, и new_event_loop()
.
Объекты политики должны реализовывать API, определенные в абстрактном базовом классе AbstractEventLoopPolicy
.
Получение и настройка политики¶
Для получения и настройки политики для текущего процесса можно использовать следующие функции:
- asyncio.get_event_loop_policy()¶
Верните текущую политику для всего процесса.
- asyncio.set_event_loop_policy(policy)¶
Установите для текущей политики всего процесса значение policy.
Если для параметра policy задано значение
None
, политика по умолчанию восстанавливается.
Объекты политики¶
Базовый класс абстрактной политики цикла обработки событий определяется следующим образом:
- class asyncio.AbstractEventLoopPolicy¶
Абстрактный базовый класс для политик asyncio.
- 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¶
Политика asyncio по умолчанию. Используется
SelectorEventLoop
в Unix иProactorEventLoop
в Windows.Нет необходимости устанавливать политику по умолчанию вручную. asyncio настроен на автоматическое использование политики по умолчанию.
Изменено в версии 3.8: В Windows значение
ProactorEventLoop
теперь используется по умолчанию.Примечание
В версиях Python 3.10.9, 3.11.1 и 3.12 метод
get_event_loop()
политики asyncio по умолчанию выдаетDeprecationWarning
, если нет запущенного цикла обработки событий и текущий цикл не задан. В каком-нибудь будущем выпуске Python это станет ошибкой.
- class asyncio.WindowsSelectorEventLoopPolicy¶
Альтернативная политика цикла обработки событий, использующая реализацию цикла обработки событий
SelectorEventLoop
.Availability: Окна.
- class asyncio.WindowsProactorEventLoopPolicy¶
Альтернативная политика цикла обработки событий, использующая реализацию цикла обработки событий
ProactorEventLoop
.Availability: Окна.
Наблюдатели за процессом¶
Process watcher позволяет настраивать то, как цикл обработки событий отслеживает дочерние процессы в Unix. В частности, цикл обработки событий должен знать, когда дочерний процесс завершился.
В asyncio дочерние процессы создаются с помощью функций create_subprocess_exec()
и loop.subprocess_exec()
.
asyncio определяет абстрактный базовый класс AbstractChildWatcher
, который должны реализовывать дочерние наблюдатели, и имеет четыре различные реализации: ThreadedChildWatcher
(настроен для использования по умолчанию), MultiLoopChildWatcher
, SafeChildWatcher
, и FastChildWatcher
.
Смотрите также раздел Subprocess and Threads.
Следующие две функции можно использовать для настройки реализации наблюдателя дочерних процессов, используемой в цикле обработки событий asyncio:
- asyncio.get_child_watcher()¶
Верните текущего дочернего наблюдателя для текущей политики.
- asyncio.set_child_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¶
Эта реализация запускает новый ожидающий поток для каждого запуска подпроцесса.
Он работает надежно, даже если цикл обработки событий asyncio выполняется в неосновном потоке операционной системы.
При обработке большого количества дочерних процессов нет заметных накладных расходов (O(1) каждый раз, когда дочерний процесс завершается), но запуск потока для каждого процесса требует дополнительной памяти.
Этот наблюдатель используется по умолчанию.
Добавлено в версии 3.8.
- class asyncio.MultiLoopChildWatcher¶
Эта реализация регистрирует обработчик сигнала
SIGCHLD
при создании экземпляра. Это может нарушить работу стороннего кода, который устанавливает пользовательский обработчик для сигналаSIGCHLD
.Наблюдатель избегает прерывания других процессов, порождающих код, путем явного опроса каждого процесса по сигналу
SIGCHLD
.После установки наблюдателя нет никаких ограничений на запуск подпроцессов из разных потоков.
Решение является безопасным, но оно сопряжено со значительными накладными расходами при обработке большого количества процессов (O(n) каждый раз при получении a
SIGCHLD
).Добавлено в версии 3.8.
- class asyncio.SafeChildWatcher¶
Эта реализация использует активный цикл обработки событий из основного потока для обработки сигнала
SIGCHLD
. Если в главном потоке нет запущенного цикла обработки событий, другой поток не может запустить подпроцесс (вызывается:exc:RuntimeError).Наблюдатель избегает прерывания других процессов, порождающих код, путем явного опроса каждого процесса по сигналу
SIGCHLD
.Это решение так же безопасно, как
MultiLoopChildWatcher
, и имеет ту же сложность, что и O (n), но для работы требуется запущенный цикл обработки событий в главном потоке.
- class asyncio.FastChildWatcher¶
Эта реализация восстанавливает все завершенные процессы, вызывая
os.waitpid(-1)
напрямую, возможно, нарушая другие процессы, вызывающие код, и ожидая их завершения.При обработке большого количества дочерних элементов нет заметных накладных расходов (O(1) каждый раз, когда дочерний элемент завершает работу).
Для работы этого решения требуется запущенный цикл обработки событий в главном потоке, как
SafeChildWatcher
.
- class asyncio.PidfdChildWatcher¶
Эта реализация опрашивает файловые дескрипторы процессов (pidfd) в ожидании завершения дочернего процесса. В некотором смысле,
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())