Политики
Политика цикла событий — это глобальный объект, используемый для получения и установки текущего цикла событий, а также для создания новых циклов событий. По умолчанию политика может быть заменена на встроенные альтернативы для использования разных реализаций циклов событий или заменена пользовательской политикой, которая может переопределять это поведение.
Объект политики получает и устанавливает отдельный цикл событий на контекст. По умолчанию это на каждый поток, хотя пользовательские политики могут определять контекст по-другому.
Пользовательские политики циклов событий могут управлять поведением 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.Доступность: Windows.
-
class asyncio.WindowsProactorEventLoopPolicy -
Альтернативная политика цикла событий, использующая реализацию цикла событий
ProactorEventLoop.Доступность: Windows.
Наблюдатели за процессами
Наблюдатель за процессами позволяет настроить, как цикл событий отслеживает дочерние процессы в Unix. В частности, циклу событий нужно знать, когда дочерний процесс завершился.
В asyncio дочерние процессы создаются с помощью функций create_subprocess_exec() и loop.subprocess_exec().
asyncio определяет абстрактный базовый класс AbstractChildWatcher, который должны реализовывать наблюдатели за дочерними процессами, и имеет четыре различных реализации: ThreadedChildWatcher (настроен по умолчанию), MultiLoopChildWatcher, SafeChildWatcher и FastChildWatcher.
См. также раздел Подпроцессы и потоки.
Для настройки реализации наблюдателя за дочерними процессами, используемой циклом событий asyncio, можно использовать следующие две функции:
-
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 -
Эта реализация запускает новый ожидающий поток для каждого запуска подпроцесса.
Она работает надежно даже когда цикл событий asyncio выполняется в потоке ОС, отличном от основного.
Нет заметной нагрузки при обработке большого количества дочерних процессов (O(1) каждый раз, когда дочерний процесс завершается), но запуск потока на процесс требует дополнительной памяти.
Этот наблюдатель используется по умолчанию.
Добавлена в версии 3.8.
-
class asyncio.MultiLoopChildWatcher -
Эта реализация регистрирует обработчик сигнала
SIGCHLDпри создании. Это может нарушить код сторонних разработчиков, который устанавливает пользовательский обработчик для сигналаSIGCHLD.Наблюдатель предотвращает нарушение другого кода, запускающего процессы, путем явного опроса каждого процесса при поступлении сигнала
SIGCHLD.Нет ограничений на запуск подпроцессов из разных потоков после установки наблюдателя.
Решение безопасно, но имеет значительную нагрузку при обработке большого количества процессов (O(n) каждый раз, когда поступает сигнал
SIGCHLD).Добавлена в версии 3.8.
-
class asyncio.SafeChildWatcher -
Эта реализация использует активный цикл событий из основного потока для обработки сигнала
SIGCHLD. Если в основном потоке нет работающего цикла событий, другой поток не может запустить подпроцесс (RuntimeErrorвозникает).Наблюдатель предотвращает нарушение другого кода, запускающего процессы, путем явного опроса каждого процесса при поступлении сигнала
SIGCHLD.Это решение так же безопасно, как
MultiLoopChildWatcherи имеет такую же сложность O(N), но требует работающего цикла событий в основном потоке для работы.
-
class asyncio.FastChildWatcher -
Эта реализация собирает каждый завершившийся процесс, вызывая
os.waitpid(-1)напрямую, возможно нарушая другой код, запускающий процессы и ожидающий их завершения.Нет заметной нагрузки при обработке большого количества дочерних процессов (O(1) каждый раз, когда дочерний процесс завершается).
Это решение требует работающего цикла событий в основном потоке, как и
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())
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/library/asyncio-policy.html