політики¶
An event loop policy is a global object used to get and set the current event loop, as well as create new event loops. The default policy can be replaced with built-in alternatives to use different event loop implementations, or substituted by a custom policy that can override these behaviors.
The policy object gets and sets a separate event loop per context. This is per-thread by default, though custom policies could define context differently.
Custom event loop policies can control the behavior of
get_event_loop()
, set_event_loop()
, and new_event_loop()
.
Об’єкти політики мають реалізовувати API, визначені в AbstractEventLoopPolicy
абстрактному базовому класі.
Отримання та налаштування політики¶
Наступні функції можна використовувати для отримання та налаштування політики для поточного процесу:
- asyncio.get_event_loop_policy()¶
Повернути поточну політику для всього процесу.
- asyncio.set_event_loop_policy(policy)¶
Установіть поточну політику для всього процесу на policy.
Якщо policy встановлено на
None
, політика за замовчуванням буде відновлена.
Об’єкти політики¶
Базовий клас політики абстрактного циклу подій визначається наступним чином:
- class asyncio.AbstractEventLoopPolicy¶
Абстрактний базовий клас для асинхронних політик.
- 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¶
Стандартна асинхронна політика. Використовує
SelectorEventLoop
в Unix іProactorEventLoop
у Windows.Немає необхідності встановлювати стандартну політику вручну. asyncio налаштовано на автоматичне використання політики за замовчуванням.
Змінено в версії 3.8: У Windows
ProactorEventLoop
тепер використовується за замовчуванням.Примітка
In Python versions 3.10.9, 3.11.1 and 3.12 the
get_event_loop()
method of the default asyncio policy emits aDeprecationWarning
if there is no running event loop and no current loop is set. In some future Python release this will become an error.
- class asyncio.WindowsSelectorEventLoopPolicy¶
Альтернативна політика циклу подій, яка використовує реалізацію циклу подій
SelectorEventLoop
.Наявність: Windows.
- class asyncio.WindowsProactorEventLoopPolicy¶
Альтернативна політика циклу подій, яка використовує реалізацію циклу подій
ProactorEventLoop
.Наявність: Windows.
Спостерігачі процесів¶
Спостерігач процесів дозволяє налаштувати те, як цикл подій відстежує дочірні процеси в Unix. Зокрема, цикл подій повинен знати, коли завершився дочірній процес.
В asyncio дочірні процеси створюються за допомогою функцій create_subprocess_exec()
і loop.subprocess_exec()
.
asyncio визначає абстрактний базовий клас AbstractChildWatcher
, який повинні реалізувати дочірні спостерігачі, і має чотири різні реалізації: ThreadedChildWatcher
(налаштований для використання за замовчуванням), MultiLoopChildWatcher
, SafeChildWatcher
і FastChildWatcher
.
Дивіться також розділ Subprocess and Threads.
Наступні дві функції можна використовувати для налаштування реалізації спостерігача дочірніх процесів, що використовується циклом асинхронних подій:
- 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¶
Ця реалізація запускає новий потік очікування для кожного породження підпроцесу.
Він працює надійно, навіть якщо цикл асинхронних подій виконується в неосновному потоці ОС.
There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates), but starting a thread per process requires extra memory.
Цей спостерігач використовується за замовчуванням.
Нове в версії 3.8.
- class asyncio.MultiLoopChildWatcher¶
Ця реалізація реєструє обробник сигналу
SIGCHLD
під час створення екземпляра. Це може порушити код третьої сторони, який встановлює спеціальний обробник для сигналуSIGCHLD
.Спостерігач уникає порушення інших процесів створення коду, явно опитуючи кожен процес за сигналом
SIGCHLD
.Немає обмежень для запуску підпроцесів з різних потоків після встановлення спостерігача.
The solution is safe but it has a significant overhead when handling a big number of processes (O(n) each time a
SIGCHLD
is received).Нове в версії 3.8.
- class asyncio.SafeChildWatcher¶
Ця реалізація використовує активний цикл подій з основного потоку для обробки сигналу
SIGCHLD
. Якщо основний потік не має запущеного циклу подій, інший потік не може породити підпроцес (виникаєRuntimeError
).Спостерігач уникає порушення інших процесів створення коду, явно опитуючи кожен процес за сигналом
SIGCHLD
.This solution is as safe as
MultiLoopChildWatcher
and has the same O(n) complexity but requires a running event loop in the main thread to work.
- class asyncio.FastChildWatcher¶
Ця реалізація збирає всі завершені процеси шляхом безпосереднього виклику
os.waitpid(-1)
, можливо, порушуючи інші процеси породження коду та чекаючи їх завершення.There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates).
Для роботи цього рішення потрібен запущений цикл подій у головному потоці, як
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())