Циклы событий
Исходный код: Lib/asyncio/events.py
18.5.2.1. Функции цикла событий
Следующие функции являются удобными сокращениями для доступа к методам глобальной политики. Обратите внимание, что это обеспечивает доступ к политике по умолчанию, если альтернативная политика не была установлена вызовом set_event_loop_policy() ранее в процессе выполнения.
-
asyncio.get_event_loop() -
Эквивалентно вызову
get_event_loop_policy().get_event_loop().
-
asyncio.set_event_loop(loop) -
Эквивалентно вызову
get_event_loop_policy().set_event_loop(loop).
-
asyncio.new_event_loop() -
Эквивалентно вызову
get_event_loop_policy().new_event_loop().
18.5.2.2. Доступные циклы событий
В настоящее время asyncio предоставляет две реализации циклов событий: SelectorEventLoop и ProactorEventLoop.
-
class asyncio.SelectorEventLoop -
Цикл событий, основанный на модуле
selectors. ПодклассAbstractEventLoop.Использует наиболее эффективный селектор, доступный на платформе.
В Windows поддерживаются только сокеты (например, не поддерживаются трубы): см. документацию MSDN по select.
-
class asyncio.ProactorEventLoop -
Цикл событий Proactor для Windows, использующий «порты завершения ввода-вывода» (IOCP). Подкласс
AbstractEventLoop.Доступность: Windows.
Пример использования ProactorEventLoop в Windows:
import asyncio, sys
if sys.platform == 'win32':
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
18.5.2.3. Поддержка платформ
Модуль asyncio был разработан для портативности, но каждая платформа всё же имеет незначительные различия и может не поддерживать все возможности asyncio.
18.5.2.3.1. Windows
Общие ограничения циклов событий Windows:
-
create_unix_connection()иcreate_unix_server()не поддерживаются: семейство сокетовsocket.AF_UNIXспецифично для UNIX -
add_signal_handler()иremove_signal_handler()не поддерживаются -
EventLoopPolicy.set_child_watcher()не поддерживается.ProactorEventLoopподдерживает подпроцессы. Он имеет только одну реализацию для отслеживания дочерних процессов, её не нужно настраивать.
SelectorEventLoop специфические ограничения:
-
SelectSelectorиспользуется, который поддерживает только сокеты и ограничен 512 сокетами. -
add_reader()иadd_writer()принимают только дескрипторы файлов сокетов - Трубы не поддерживаются (например,
connect_read_pipe(),connect_write_pipe()) -
Подпроцессы не поддерживаются (например,
subprocess_exec(),subprocess_shell())
ProactorEventLoop специфические ограничения:
-
create_datagram_endpoint()(UDP) не поддерживается -
add_reader()иadd_writer()не поддерживаются
Разрешение монотонных часов в Windows обычно составляет около 15,6 мс. Лучшее разрешение — 0,5 мс. Разрешение зависит от оборудования (доступность HPET) и конфигурации Windows. См. asyncio отложенные вызовы.
Изменено в версии 3.5: ProactorEventLoop теперь поддерживает SSL.
18.5.2.3.2. Mac OS X
Устройства символьного ввода-вывода, такие как PTY, хорошо поддерживаются начиная с Mavericks (Mac OS 10.9). Они вообще не поддерживаются в Mac OS 10.5 и более ранних версиях.
В Mac OS 10.6, 10.7 и 10.8 циклом событий по умолчанию является SelectorEventLoop, который использует selectors.KqueueSelector. selectors.KqueueSelector не поддерживает устройства символьного ввода-вывода в этих версиях. SelectorEventLoop может быть использован с SelectSelector или PollSelector для поддержки устройств символьного ввода-вывода в этих версиях Mac OS X. Пример:
import asyncio import selectors selector = selectors.SelectSelector() loop = asyncio.SelectorEventLoop(selector) asyncio.set_event_loop(loop)
18.5.2.4. Политики циклов событий и политика по умолчанию
Управление циклом событий абстрагировано с помощью шаблона политики, чтобы обеспечить максимальную гибкость для пользовательских платформ и фреймворков. На протяжении всего выполнения процесса единственный глобальный объект политики управляет циклами событий, доступными для процесса в зависимости от контекста вызова. Политика — это объект, реализующий интерфейс AbstractEventLoopPolicy.
Для большинства пользователей asyncio политика никогда не должна обрабатываться явно, так как глобальная политика по умолчанию достаточна (см. ниже).
Функции уровня модуля get_event_loop() и set_event_loop() предоставляют удобный доступ к циклам событий, управляемым политикой по умолчанию.
18.5.2.5. Интерфейс политики цикла событий
Политика цикла событий должна реализовывать следующий интерфейс:
-
class asyncio.AbstractEventLoopPolicy -
Политика цикла событий.
-
get_event_loop() -
Получить цикл событий для текущего контекста.
Возвращает объект цикла событий, реализующий интерфейс
AbstractEventLoop. Если вызов происходит из корутины, возвращает текущий работающий цикл событий.Вызывает исключение, если для текущего контекста не установлен цикл событий, и текущая политика не определяет создание одного. Он никогда не должен возвращать
None.Изменено в версии 3.6.
-
set_event_loop(loop) -
Установить цикл событий для текущего контекста на loop.
-
new_event_loop() -
Создать и вернуть новый объект цикла событий в соответствии с правилами этой политики.
Если необходимо установить этот цикл как цикл событий для текущего контекста, необходимо явно вызвать
set_event_loop().
-
По умолчанию политика определяет контекст как текущую нить и управляет циклом событий на нить, взаимодействуя с asyncio. Если у текущей нити ещё нет связанного с ней цикла событий, метод политики по умолчанию get_event_loop() создаёт его при вызове из главной нити, но в противном случае вызывает RuntimeError.
18.5.2.6. Доступ к глобальной политике цикла событий
-
asyncio.get_event_loop_policy() -
Получить текущую политику цикла событий.
-
asyncio.set_event_loop_policy(policy) -
Установить текущую политику цикла событий. Если policy имеет значение
None, восстанавливается политика по умолчанию.
18.5.2.7. Настройка политики цикла событий
Для реализации новой политики цикла событий рекомендуется унаследовать от конкретной политики цикла событий по умолчанию 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–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/asyncio-eventloops.html