18.5.2. Циклы событий
Исходный код: 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(цикл событий)¶ Эквивалентно вызову
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специфично для UNIXadd_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 не поддерживает символьные устройства в этих
версиях. Для поддержки символьных устройств в этих версиях Mac OS X можно использовать SelectorEventLoop с
SelectSelector или PollSelector. Пример:
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.
-
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(политика)¶ Устанавливает текущую политику цикла событий. Если политика равно
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()
# Сделать что-то с loop ...
return loop
asyncio.set_event_loop_policy(MyEventLoopPolicy())