Политика

Политика цикла событий - это глобальный объект, используемый для получения и установки текущего 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.

Не рекомендуется, начиная с версии 3.12.

set_child_watcher(watcher)

Установите текущий наблюдатель дочернего процесса на watcher.

Эта функция специфична для Unix.

Не рекомендуется, начиная с версии 3.12.

asyncio поставляется со следующими встроенными политиками:

class asyncio.DefaultEventLoopPolicy

Политика asyncio по умолчанию. Используется SelectorEventLoop на Unix и ProactorEventLoop на Windows.

Нет необходимости устанавливать политику по умолчанию вручную. asyncio настроен на автоматическое использование политики по умолчанию.

Изменено в версии 3.8: В Windows по умолчанию теперь используется ProactorEventLoop.

Не рекомендуется, начиная с версии 3.12: Метод get_event_loop() политики asyncio по умолчанию теперь выдает сообщение DeprecationWarning, если нет текущего цикла событий и он решает его создать. В каком-нибудь будущем выпуске Python это станет ошибкой.

class asyncio.WindowsSelectorEventLoopPolicy

Альтернативная политика цикла событий, использующая реализацию цикла событий SelectorEventLoop.

Availability: Windows.

class asyncio.WindowsProactorEventLoopPolicy

Альтернативная политика цикла событий, использующая реализацию цикла событий ProactorEventLoop.

Availability: Windows.

Наблюдатели за процессом

Наблюдатель процесса позволяет настраивать, как цикл событий следит за дочерними процессами в Unix. В частности, цикл событий должен знать, когда дочерний процесс завершился.

В asyncio дочерние процессы создаются с помощью функций create_subprocess_exec() и loop.subprocess_exec().

asyncio определяет абстрактный базовый класс AbstractChildWatcher, который должны реализовывать дочерние наблюдатели, и имеет четыре различных реализации: ThreadedChildWatcher (настроен на использование по умолчанию), MultiLoopChildWatcher, SafeChildWatcher и FastChildWatcher.

См. также раздел Subprocess and Threads.

Следующие две функции можно использовать для настройки реализации наблюдателя дочерних процессов, используемой циклом событий asyncio:

asyncio.get_child_watcher()

Возвращает текущий дочерний наблюдатель для текущей политики.

Не рекомендуется, начиная с версии 3.12.

asyncio.set_child_watcher(watcher)

Устанавливает текущий дочерний наблюдатель на watcher для текущей политики. watcher должен реализовывать методы, определенные в базовом классе AbstractChildWatcher.

Не рекомендуется, начиная с версии 3.12.

Примечание

Сторонние реализации циклов событий могут не поддерживать пользовательские дочерние наблюдатели. Для таких циклов событий использование 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.

Added in version 3.8.

close()

Закройте наблюдателя.

Этот метод должен быть вызван, чтобы убедиться, что базовые ресурсы очищены.

Не рекомендуется, начиная с версии 3.12.

class asyncio.ThreadedChildWatcher

Эта реализация запускает новый поток ожидания для каждого порождения подпроцесса.

Он надежно работает, даже если цикл событий asyncio запущен в неосновном потоке ОС.

При работе с большим числом дочерних процессов заметных накладных расходов нет (O(1) при каждом завершении дочернего процесса), но запуск одного потока на процесс требует дополнительной памяти.

Этот наблюдатель используется по умолчанию.

Added in version 3.8.

class asyncio.MultiLoopChildWatcher

Эта реализация регистрирует обработчик сигнала SIGCHLD при инстанцировании. Это может нарушить работу стороннего кода, который устанавливает собственный обработчик сигнала SIGCHLD.

Наблюдатель позволяет избежать прерывания других процессов, порождающих код, путем явного опроса каждого процесса по сигналу SIGCHLD.

После установки наблюдателя нет ограничений на запуск подпроцессов из разных потоков.

Это решение безопасно, но при обработке большого количества процессов оно имеет значительные накладные расходы (O(n) при каждом получении SIGCHLD).

Added in version 3.8.

Не рекомендуется, начиная с версии 3.12.

class asyncio.SafeChildWatcher

Эта реализация использует активный цикл событий из главного потока для обработки сигнала SIGCHLD. Если в главном потоке не запущен цикл событий, другой поток не может породить подпроцесс (RuntimeError поднимается).

Наблюдатель позволяет избежать прерывания других процессов, порождающих код, путем явного опроса каждого процесса по сигналу SIGCHLD.

Это решение так же безопасно, как и MultiLoopChildWatcher, и имеет ту же O(n) сложность, но для его работы требуется работающий цикл событий в главном потоке.

Не рекомендуется, начиная с версии 3.12.

class asyncio.FastChildWatcher

Эта реализация получает все завершенные процессы, вызывая os.waitpid(-1) напрямую, что, возможно, нарушает другой код, порождающий процессы и ожидающий их завершения.

При работе с большим числом дочерних программ (O(1) при каждом завершении дочерней программы) заметных накладных расходов нет.

Для работы этого решения требуется запущенный цикл событий в главном потоке, как SafeChildWatcher.

Не рекомендуется, начиная с версии 3.12.

class asyncio.PidfdChildWatcher

Эта реализация опрашивает дескрипторы файлов процессов (pidfds), чтобы ожидать завершения дочерних процессов. В некоторых отношениях PidfdChildWatcher является «златовласой» реализацией дочернего наблюдателя. Она не требует сигналов или потоков, не вмешивается в процессы, запущенные вне цикла событий, и линейно масштабируется с количеством подпроцессов, запущенных циклом событий. Основным недостатком является то, что pidfds специфичен для Linux и работает только на последних (5.3+) ядрах.

Added in version 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())