Политика

Политика цикла событий - это глобальный объект для каждого процесса, который контролирует управление циклом событий. Каждый цикл событий имеет политику по умолчанию, которую можно изменить и настроить с помощью API политики.

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

Используя пользовательскую политику цикла событий, можно настроить поведение функций 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()

Получение объекта наблюдателя дочернего процесса.

Возвращает объект watcher, реализующий интерфейс AbstractChildWatcher.

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

set_child_watcher(watcher)

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

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

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

class asyncio.DefaultEventLoopPolicy

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

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

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

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()

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

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 при инстанцировании. Это может нарушить сторонний код, который устанавливает собственный обработчик для сигнала :py .

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

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

Добавлено в версии 3.8.

class asyncio.SafeChildWatcher

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

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

Это решение так же безопасно, как 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())
Вернуться на верх