Событийный цикл¶
Исходный код: Lib/asyncio/events.py, Lib/asyncio/base_events.py
Preface
Событийный цикл является ядром любого asyncio приложения. Событийные циклы выполняют: асинхронные задачи, коллбэки, сетевые операции ввода-вывода и подпроцессы.
Разработчики приложений обычно пользуются высокоуровневыми функциями asyncio,
(например, asyncio.run()
), с редкой потребнотью ссылаться на объект цикла или вызов его
методов. Этот раздел предназначен в основном для авторов низкоуровневого
кода, такого как библиотеки и фреймворкови, которым необходим более точный контроль над
работой событийного цикла.
Obtaining the Event Loop
Следующие низкоуровневые функции можно использовать для получения, установки или создания событийного цикла:
-
asyncio.
get_running_loop
()¶ Возвращает работающий событийный цикл в текущем потоке ОС.
Если событийный цикл не выполняется, возникает
RuntimeError
. Эта функция может быть вызвана только из корутина или коллбэка.Добавлено в версии 3.7.
-
asyncio.
get_event_loop
()¶ Получение текущего событийного цикла.
Если в текущем потоке ОС не установлен текущий событийный цикл, поток ОС является основным, а
set_event_loop()
ещё не вызывался, asyncio создаст новый событийный цикл и установит его в качестве текущего.Поскольку у этой функция довольно сложное поведение (особенно когда используются настраиваемые политики событийного цикла), использование функции
get_running_loop()
предпочтительно дляget_event_loop()
корутин и обратных вызовов.Для создания и ручного закрытия событийного цикла также рекомендуется использовать функцию
asyncio.run()
вместо использования более низкоуровневых функций.
-
asyncio.
set_event_loop
(loop)¶ Устанавливает loop в качестве текущего событийного цикла для текущего потока ОС.
-
asyncio.
new_event_loop
()¶ Создание нового объекта событийного цикла.
Обратите внимание, что поведение функций get_event_loop()
, set_event_loop()
и new_event_loop()
могут быть изменены установкой пользовательской политики событийног цикла.
Contents
Эта страница документации содержит следующие разделы
- Раздел Методы событийного цикла является справочной документацией по API событийого цикла;
- Раздел Обработчики коллбэков документирует
Handle
иTimerHandle
сущности возвращаемые из запланированных методов таких какloop.call_soon()
иloop.call_later()
; - Раздел Объекты сервера документирует возвращаемые типы
событийного цикла, например
loop.create_server()
; - Раздел Событийный цикл документация для классов
SelectorEventLoop
иProactorEventLoop
; - В разделе Примеры показано, как работать с API событийного цикла.
Методы событийного цикла¶
Событийные циклы содержат низкоуровневое API для следующего:
- Запуск и остановка цикла
- Планирование коллбэков
- Планирование отложенных коллбэков
- Создание фьючерсов и задач
- Открытие сетевых подключений
- Создание сетевых серверов
- Передача файлов
- Обновление TLS
- Наблюдение за файловыми дескрипторами
- Непосредственная работа с объектами сокетов
- DNS
- Работа с пайпами
- Сигналы Unix
- Выполнение кода в пулах потоков или процессов
- API обработки ошибок
- Активация возможности режима отладки
- Управление подпроцессами
Запуск и остановка цикла¶
-
loop.
run_until_complete
(future)¶ Выполнение до завершения future (сущность
Future
).Если аргумент является объектом корутиной, то его неявно планируется запустить как
asyncio.Task
.Возвращается результат Future или вызывается исключение.
-
loop.
run_forever
()¶ Выполните событийный цикл до вызова
stop()
.Если
stop()
вызывается до вызоваrun_forever()
, цикл опрашивает селектор ввода/вывода один раз с нулевым таймаутом, выполняет все коллбэки, запланированные в ответ на события ввода/вывода (и те, которые уже были запланированы), и затем завершает работу.Если
stop()
вызывается во время выполненияrun_forever()
, цикл выполнит текущий пакет обратных вызовов и затем завершит работу. Обратите внимание, что новые коллбэки, запланированные обратными вызовами, в этом случае выполняться не будут; вместо этого они запускаются при следующем вызовеrun_forever()
илиrun_until_complete()
.
-
loop.
stop
()¶ Остановка событийного цикла.
-
loop.
is_running
()¶ Возвращает
True
, если в событийный цикл уже работает.
-
loop.
is_closed
()¶ Возвращает
True
, если событийный цикл был закрыт.
-
loop.
close
()¶ Закрытие событийного цикла.
Цикл не должен выполняться при вызове этой функции. Все отложенные обратные вызовы будут отброшены.
Этот метод очищает все очереди и отключает исполнителя, не дожидаясь его завершения.
Этот метод является идемпотентным и необратимым. После закрытия цикла событий не следует вызывать другие методы.
-
coroutine
loop.
shutdown_asyncgens
()¶ Запланировать закрытие всех открытых объектов асинхронного генератора с помощью вызова
aclose()
. После вызова данного метода событийный цикл выдаст предупреждение в случае итерации нового асинхронного генератора. Используется для надежного завершения всех запланированных асинхронных генераторов.Обратите внимание, что нет необходимости вызывать эту функцию при использовании
asyncio.run()
.Пример:
try: loop.run_forever() finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()
Добавлено в версии 3.6.
Планирование коллбэков¶
-
loop.
call_soon
(callback, *args, context=None)¶ Запланируйте вызов callback колбэк с аргументами args на следующей итерации цикла событий.
Коллбэки вызываются в порядке их регистрации. Каждый коллбэк вызывается ровно один раз.
Необязательный ключевой аргумент context позволяет указать настраиваемый
contextvars.Context
для запуска callback. Если используется текущий контекст, то context не предоставляется.Возвращается сущность
asyncio.Handle
, который можно используемый позже для отмены коллбэка.Данный метод не потокобезопасен.
-
loop.
call_soon_threadsafe
(callback, *args, context=None)¶ Потокобезопасный вариант
call_soon()
. Используется для планирования коллбэков из другмх потоков.См. раздел конкурентность и многопоточность документации.
Изменено в версии 3.7: Также добавлен context только в виде ключевого параметра. См. PEP 567 для получения дополнительной информации.
Примечание
Большинство функций планировщика asyncio
не позволяют передавать ключевые
аргументы. Для этого используется functools.partial()
:
# запланировать "print("Hello", flush=True)"
loop.call_soon(
functools.partial(print, "Hello", flush=True))
Использование частичных объектов обычно удобнее, чем использование лямбд, так как asyncio могут лучше визуализировать частичные объекты в сообщениях об отладке и ошибках.
Планирование отложенных коллбэков¶
Событийный цикл предоставляет механизмы планирования функций коллбэка в будущем. Событийный цикл использует монотонный часы для отслеживания времени.
-
loop.
call_later
(delay, callback, *args, context=None)¶ Запланировать вызов callback после заданного delay числа секунд (может быть int или float).
Возвращает сущность
asyncio.TimerHandle
, которая может использоваться для отмены коллбэка.Коллбэк вызывается ровно один раз. Если два коллбэка фиксируются в одно и то же время, порядок их вызова не определен.
Необязательный позиционный args будет передан в коллбэк при его вызове. Если требуется вызвать коллбэк с ключевыми аргументами, используйте
functools.partial()
.Необязательный ключевой аргумент context позволяет указать настраиваемое
contextvars.Context
для запуска callback. Используется текущий контекст, если context не передаётся.Изменено в версии 3.7: Также добавлен context только в виде ключевого параметра. См. PEP 567 для получения дополнительной информации.
Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией событийного цикла по умолчанию, delay не может превышать одного дня. Это зафиксировано в Python 3.8.
-
loop.
call_at
(when, callback, *args, context=None)¶ Планирование коллбэка для вызова в данной when абсолютной временной метке (int или float) с использованием той же временной ссылки, что и
loop.time()
.Поведение этого метода совпадает с поведением
call_later()
.Возвращается сущность
asyncio.TimerHandle
, которая может использоваться для отмены коллбэка.Изменено в версии 3.7: Также добавлен context только в виде ключевого параметра. См. PEP 567 для получения дополнительной информации.
Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией событийного цикла по умолчанию, разница между when и текущим временем не может превышать одного дня. Это зафиксировано в Python 3.8.
-
loop.
time
()¶ Возвращает текущее время в виде
float
значения согласно внутренним монотонным часам событийного цикла.
Примечание
Изменено в версии 3.8: В Python 3.7 и более ранних таймаутах (относительные delay или абсолютные when) не должно превышать одного дня. Это зафиксировано в Python 3.8.
См.также
Функцию asyncio.sleep()
.
Создание фьючерсов и задач¶
-
loop.
create_future
()¶ Создаёт объект
asyncio.Future
, присоединенный к событийному циклу.Это предпочтительный способ создания фьючерса в asyncio. Это позволяет событийным циклам сторонних производителей предоставлять альтернативные реализации объекта Future (с более высокой производительностью или инструментарием).
Добавлено в версии 3.5.2.
-
loop.
create_task
(coro, *, name=None)¶ Планирование выполнения Корутины. Возврат объекта
Task
.Событийные циклы сторонних производителей могут использовать собственный субкласс
Task
для обеспечения совместимости. В этом случае тип результата представляет собой подклассTask
.Если аргумент name указан и не
None
, он устанавливается в качестве имени задачи с помощьюTask.set_name()
.Изменено в версии 3.8: Добавлен параметр
name
.
-
loop.
set_task_factory
(factory)¶ Задание фабрики задач, которая будет используемый по
loop.create_task()
.Если factory
None
, будет установлена фабрика задач по умолчанию. В противном случае factory должен быть вызываемым с сигнатурой(loop, coro)
, где loop - ссылка на активный событийный цикл, а coro - корутин. Вызываемый объект должен возвращать объект совместимыйasyncio.Future
.
-
loop.
get_task_factory
()¶ Возвращает фабрику задач или
None
, если она используется по умолчанию.
Открытие сетевых подключений¶
-
coroutine
loop.
create_connection
(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None)¶ Открытие поточного транспортного соединения с заданным адресом, указанным host и port.
Семейство сокетов может быть
AF_INET
илиAF_INET6
в зависимости от host (или передан аргумент family).Тип сокета будет
SOCK_STREAM
.protocol_factory должен быть вызываемым, возвращающим реализацию asyncio протокола.
Этот метод попытается установить соединение в фоновом режиме. В случае успеха он возвращает пару
(transport, protocol)
.Хронологический обзор основной операции выглядит следующим образом:
- Установление соединения и для него создается транспорт.
- Вызывается protocol_factory без аргументов с ожиданием возвращения сущности протокола.
- Сущность протокола связывается с транспортом путем вызова его
connection_made()
метода. - При успехе возвращается кортеж
(transport, protocol)
.
Созданный транспорт является зависящим от реализации двунаправленным потоком.
Другие аргументы:
ssl: если передан и не ложен, то создается SSL/TLS транспорт (по умолчанию создается обычный TCP-транспорт). Если ssl объект
ssl.SSLContext
, этот контекст используется для создания транспорта; если sslTrue
, возвращается используемый контекст по умолчанию отssl.create_default_context()
.См.также
server_hostname задаёт или переопределяет имя узла, которое является целевым серверным сертификатом используемым для сопоставления. Должен быть передан если ssl не
None
. По умолчанию используется значение аргумента host. Если host пуст, то нет значения по умолчанию и необходимо передать значение для server_hostname. Если server_hostname пустая строка, сопоставление имён хостов отключается (что является серьезным защитным риском, допускающий потенциальные атаки человека по середине).family, proto, flags являются дополнительным семейством адресов, протокола и флагов, передаваемые в getaddrinfo() для host разрешения. Если указано, все они должны быть целыми числами из соответствующих констант модуля
socket
.happy_eyeballs_delay, если передается, то активируется Happy Eyeballs для данного подключения. Это должно быть число с плавающей запятой, представляющее количество времени в секундах. Для ожидания завершения попытки подключения перед запуском следующей параллельной попытки. Это «Задержка попытки подключения», как определено в RFC 8305. Разумное значение по умолчанию, рекомендуемое RFC
0.25
(250 миллисекунд).interleave управляет переупорядочением адресов при разрешении имени хоста в несколько IP-адресов. Если
0
или не указано, переупорядочение не выполняется, а адреса возвращаются в порядке, возвращенномgetaddrinfo()
. Если положительное целое число , адреса чередуются по семейству адресов и данное целое число интерпретируется как «Счетчик первого семейства адресов», как определено в RFC 8305. Значение по умолчанию -0
, если happy_eyeballs_delay не определено и1
, если иначе.sock если передаётся, то должен существовать к уже подключенному
socket.socket
объекту, который должен быть использован транспортом. Если sock передан, то определять host, port, family, proto, flags, happy_eyeballs_delay, interleave и local_addr не нужно.local_addr если передан то
(local_host, local_port)
кортеж используется для привязки сокета к локальному адресу. local_host и local_port просматриваются с помощьюgetaddrinfo()
, аналогично host и port.ssl_handshake_timeout (для TLS подключений) время в секундах ожидания завершения подтверждения по TLS перед прерыванием соединения. По умолчанию
60.0
секунд, еслиNone
.
Добавлено в версии 3.8: Добавлены параметры happy_eyeballs_delay и interleave.
Алгоритм happy eyeballs: успех с двумя хостами стека. Когда работают серверные IPv4 пути и протоколы, а IPv6 пути и протоколы нет, клиент с двойным стеком приложения испытывает значительную задержку соединения по сравнению с только IPv4 клиентом. Это нежелательно, поскольку приводит двойному вызову стека клиента, что ухудшает работу пользователя. Этот документ указывает требования к алгоритмам, уменьшающим задержку видимости пользователя и предоставляет алгоритм.
Для получения дополнительной информации: https://tools.ietf.org/html/rfc6555
Добавлено в версии 3.7: Параметр ssl_handshake_timeout.
Изменено в версии 3.6: Опция сокета
TCP_NODELAY
устанавливается по умолчанию для всех TCP-соединений.Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop
.См.также
Функция
open_connection()
является альтернативой высокоуровневого API. Возвращает пару (StreamReader
,StreamWriter
) которые можно использовать непосредственно в async/await коде.
-
coroutine
loop.
create_datagram_endpoint
(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None)¶ Примечание
Параметр reuse_address больше не поддерживается, так как используется
SO_REUSEADDR
вызывает серьезную озабоченность в плане безопасности UDP. Явная передачаreuse_address=True
вызовет исключение.Если несколько процессов с различными UID назначают сокеты идентичному UDP адресу сокета с
SO_REUSEADDR
, входящие пакеты могут случайным образом распределяются между сокетами.Для поддерживаемых платформ reuse_port можно используемый в качестве замены подобной функциональностьи. вместо reuse_port используется
SO_REUSEPORT
, который запрещает процессам с различными идентификаторами UID назначать сокеты одному и тому же адресу сокета.Создаёт подключение к дейтаграмме.
Семейство сокетов может быть
AF_INET
,:py:data:~socket.AF_INET6 илиAF_UNIX
в зависимости от host (или аргумента family, если имеется).Тип сокета будет
SOCK_DGRAM
.protocol_factory должен быть вызываемым, возвращающим реализацию протокола.
При успехе возвращается кортеж
(transport, protocol)
.Другие аргументы:
- local_addr, если передан, то кортеж
(local_host, local_port)
используется для привязки сокета к локальному адресу. local_host и local_port просматриваются с помощьюgetaddrinfo()
. - remote_addr, если передан, то кортеж
(remote_host, remote_port)
используется для подключения сокета к удаленному адресу. Для просмотра remote_host и remote_port используетсяgetaddrinfo()
. - family, proto, flags опциональное семейтсва адресов, протокол
и флаги, передаваемые
getaddrinfo()
для host резолюции. Если указано, все они должны быть целыми числами из соответствующих констант модуляsocket
. - reuse_port говорит ядру разрешить привязку этого узла к
тому же порту, к которому привязаны другие существующие узлы, если они
все установили этот флаг при создании. Этот параметр не поддерживается в Windows
и некоторый Unix. Если константа
SO_REUSEPORT
отсутствует эта возможность не поддерживается. - allow_broadcast говорит ядру разрешить отправку этого узла сообщения на широковещательный адрес.
- sock необязательно может быть указан для использования существующего ранее,
подключения,
socket.socket
объект используется как транспорт. Если указан, local_addr и remote_addr следует опустить. (должен бытьNone
).
См. клиент UDP эхо протокола и сервер UDP эхо пртокола для примера.
Изменено в версии 3.4.4: Были добавлены family, proto, flags, reuse_address, reuse_port *allow_broadcast и sock.
Изменено в версии 3.8.1: Параметр reuse_address больше не поддерживается из-за проблем с безопасностью.
Изменено в версии 3.8: Добавлена поддержка Windows.
- local_addr, если передан, то кортеж
-
coroutine
loop.
create_unix_connection
(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None)¶ Создание Unix подключений.
Семейство сокетов будет
AF_UNIX
; Тип сокета будет be:py:data:~socket.SOCK_STREAM.При успехе возвращается кортеж
(transport, protocol)
.path является именем сокета домена Unix и является обязательным, без указания параметра sock. Абстрактные сокеты Unix,
str
,bytes
иPath
пути не поддерживаются.См. документацию по методу
loop.create_connection()
для получения информации о аргументах этого метода.Availability: Unix.
Добавлено в версии 3.7: Параметр ssl_handshake_timeout.
Изменено в версии 3.7: Теперь параметр path может быть путеподобным объектом.
Создание сетевых серверов¶
-
coroutine
loop.
create_server
(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)¶ Создаёт TCP сервер (тип сокета
SOCK_STREAM
) прослушивающий port адреса host.Возвращает объект
Server
.Аргументы:
- protocol_factory должен быть вызываемым, возвращающим реализацию протокола.
- Параметр host может объединять несколько типов, которые определяют, где
сервер будет прослушивать:
- Если host является строка, TCP-сервер привязан к одному сетевому интерфейсу, указаывающий host.
- Если host последовательность строк, TCP-сервер привязан ко всем сетевыем интерфейсам, указанным в последовательности.
- Если host пустая строка или
None
, привязка выполняется ко всем интерфейсам и будет возвращен список из нескольких сокетов (наиболее вероятно один для IPv4 и другой для IPv6).
- family можно установить либо
socket.AF_INET
илиAF_INET6
, чтобы заставить сокет использовать IPv4 или IPv6. Если этот параметр не установлен, family определяется по имени хоста. (по умолчаниюAF_UNSPEC
). - flags - битовая маска для
getaddrinfo()
. - sock необязательный параметр для указания использования существующего ранее объект сокета. Если указано, host и port не должны быть указаны.
- backlog максимальное количество соединений в очереди, переданных
listen()
(по умолчанию 100). - ssl может быть передан сущностью
SSLContext
для активации TLS по принятым соединениям. - reuse_address сообщает ядру повторно использовать локальный сокет в
TIME_WAIT
состояния, не дожидаясь своего естественного истечения тайм-аута. Если не указано, автоматически будет установлено значениеTrue
Unix. - reuse_port сообщает ядру разрешить привязку этой конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, если они все установили этот флаг при создании. Этот параметр не поддерживается в Windows.
- ssl_handshake_timeout (для TLS сервера) время в секундах для ожидания
для завершения подтверждения TLS перед прерыванием соединения.
60.0
секунд, еслиNone
(по умолчанию). - start_serving устанавливает
True
(по умолчанию) вынуждает созданный сервер немедленно начать принимать подключения. Если установлено значениеFalse
, пользователь должен ожидатьServer.start_serving()
илиServer.serve_forever()
, чтобы сервер начал принимать подключения.
Добавлено в версии 3.7: Добавлены параметры ssl_handshake_timeout и start_serving.
Изменено в версии 3.6: Опция сокета
TCP_NODELAY
устанавливается по умолчанию для всех TCP-соединений.Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop
.Изменено в версии 3.5.1: Параметр host может быть последовательностью строк.
См.также
Функция
start_server()
является высокоуровневой альтернативным API возвращающий паруStreamReader
иStreamWriter
которые можно использовать в async/await коде.
-
coroutine
loop.
create_unix_server
(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)¶ Похож на
loop.create_server()
, но работает с семейством сокетовAF_UNIX
.path имя сокета домена Unix и является обязательным, в отличии от sock аргумента. Также в path поддерживаются абстрактные сокеты Unix,
str
,bytes
иPath
.См. документацию по методу
loop.create_server()
для получения информации об аргументах этого метод.Availability: Unix.
Добавлено в версии 3.7: Параметры ssl_handshake_timeout и start_serving.
Изменено в версии 3.7: Теперь параметр path может быть объектом
Path
.
-
coroutine
loop.
connect_accepted_socket
(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None)¶ Обёртка уже принятого соединения пары транспорт/протокол.
Метод может быть использоваться серверами, принимающими подключения за пределами asyncio, но использующими asyncio для их обработки.
Параметры:
- protocol_factory должен быть вызываемым, возвращающим реализацию протокола.
- sock это существующий объект сокета, возвращенный из :meth:“socket.accept <socket.socket.accept>“.
- ssl может быть установлен сущностью
SSLContext
для активации SSL через принятые подключения. - ssl_handshake_timeout (для SSL подключений) время в секундах
ожидания завершения SSL-подтверждения перед прерыванием соединения.
60.0
секунд, еслиNone
(по умолчанию).
Возвращает пару
(transport, protocol)
.Добавлено в версии 3.7: Параметр ssl_handshake_timeout.
Добавлено в версии 3.5.3.
Передача файлов¶
-
coroutine
loop.
sendfile
(transport, file, offset=0, count=None, *, fallback=True)¶ Отправить file через transport. Возвращает общее число отправленных байт.
В методе используется высокопроизводительный
os.sendfile()
, если доступен.file должен быть обычным объектом файла, открытым в двоичном режиме.
offset указывает, откуда начинать чтение файла. Если определено count общее количество байтов для передачи в отличие от достижения EOF завершения файла. Позиция файла всегда обновляется, пока метод не вызывает ошибку и может использоваться
file.tell()
для получение фактического размера отправленных байтов.fallback устанавленный в значение
True
предписывает asyncio вручную читать и отправлять файл, если платформа не поддерживает системный вызов sendfile, например, в Windows или SSL сокет в Unix).Вызывается исключение
SendfileNotAvailableError
если система не поддерживает sendfile системный вызов и fallback равенFalse
.Добавлено в версии 3.7.
Обновление TLS¶
-
coroutine
loop.
start_tls
(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None)¶ Обновление существующего транспортного соединения до TLS.
Возвращает новую транспортную сущность, которую protocol должен начать использовать сразу после await. Переданная сущность transport метода start_tls больше никогда не должена быть использована.
Параметры:
- сущности transport и protocol с методами подобными
create_server()
и возвращениеcreate_connection()
. - sslcontext настраиваемая сущность
SSLContext
. - server_side передача
True
когда подключения серверной части начинают обновление (подобно созданномуcreate_server()
). - server_hostname устанавливает или переопределяет имя хоста, для сопоставленения целевого сертификата сервера.
- ssl_handshake_timeout (для TLS подключений) время в секундах
ожидания завершения подтверждения TLS перед прерыванием соединения. Если
None
то60.0
секунд (по умолчанию).
Добавлено в версии 3.7.
- сущности transport и protocol с методами подобными
Наблюдение за файловыми дескрипторами¶
-
loop.
add_reader
(fd, callback, *args)¶ Запуск мониторинга дескриптора файла fd на предмет доступности для чтения и вызов callback с указанными аргументами, как только fd будет доступен для чтения.
-
loop.
remove_reader
(fd)¶ Прекратить мониторинг дескриптора файла fd на предмет доступности для чтения.
-
loop.
add_writer
(fd, callback, *args)¶ Запуск мониторинг дескриптора файла fd на наличие записи и вызова callback с указанными аргументами, как только fd будет доступен для записи.
Используйте
functools.partial()
для передачи ключевого аргумента callback.
-
loop.
remove_writer
(fd)¶ Прекратить мониторинг дескриптора файла fd на наличие записи.
См. также раздел Поддержка платформы для знакомства с некоторыми ограничениями этих методов.
Непосредственная работа с объектами сокетов¶
В общем случае, реализации протоколов, в которых используется транспортное API
например, loop.create_connection()
и loop.create_server()
более быстрые,
чем реализации, работающих непосредственно с сокетами. Однако существуют некоторые случаи
использования, когда производительность не является критичной и работать с socket
объектами напрямую более удобно.
-
coroutine
loop.
sock_recv
(sock, nbytes)¶ Получение nbytes из sock. Асинхронная версия
socket.recv_into()
.Возврат полученных данных в виде байтового объекта.
sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Хотя этот метод документировался как корутин метод, релизы перед Python 3.7 возвращали
Future
. С Python 3.7 этоasync def
метод.
-
coroutine
loop.
sock_recv_into
(sock, buf)¶ Прием данных из sock в буфер buf. Смоделированный после блокирующего метода
socket.recv_into()
.Возвращает количество байтов, записанных в буфер.
sock должен быть неблокирующим сокетом.
Добавлено в версии 3.7.
-
coroutine
loop.
sock_sendall
(sock, data)¶ Отправить data в сокет sock. Асинхронная версия
socket.sendall()
.Метод продолжает посылать данные в сокет до тех пор, пока не будут отправлены все data данные или не произойдет ошибка.
None
возвращается при успехе. При ошибке возникает исключение. Кроме того, невозможно определить, сколько данных, если таковые имеются, было успешно обработано принимающей стороной соединения.sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Несмотря на то, что метод всегда документировался как корутин метод, перед Python 3.7 возвращался
Future
. Начиная с Python 3.7 этоasync def
метод.
-
coroutine
loop.
sock_connect
(sock, address)¶ Подключение sock к удаленному сокету с address.
Асинхронная версия
socket.connect()
.sock должен быть неблокирующим сокетом.
Изменено в версии 3.5.2:
address
больше не нужно резолвить.sock_connect
попытается проверить, резолвлен ли address с помощью вызоваsocket.inet_pton()
. В противном случаеloop.getaddrinfo()
будет использоваться для резолвинга address.См.также
-
coroutine
loop.
sock_accept
(sock)¶ Принятие подключения. Смоделированный после блокирующего
socket.accept()
метода.Сокет должен быть привязан к адресу и прослушивающего подключения. Возвращаемое значение является парой
(conn, address)
где conn - объект сокета new, используемый для передачи и приема данных из соединения, а address - адрес, привязанный к сокету на другом конце соединения.sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Несмотря на то, что метод всегда документировался как корутин метод, перед Python 3.7 возвращал
Future
. С Python 3.7 этоasync def
метод.См.также
-
coroutine
loop.
sock_sendfile
(sock, file, offset=0, count=None, *, fallback=True)¶ По возможности отправляет файл с помощью высокопроизводительного
os.sendfile
. Возвращает общее число отправленных байт.Асинхронная версия
socket.sendfile()
.sock должен быть неблокирующим
socket.SOCK_STREAM
socket
.file должен быть обычным объектом файла, открытым в двоичном режиме.
offset указывает, откуда начинать чтение файла. Если определено count, общее количество передаваемых байтов в отличие от достижения EOF завершения файла. Позиция файла всегда обновляется, даже когда метод вызывает ошибку, и
file.tell()
может быть использован для получения фактического размера отправленных байтов.fallback, если установлено значение
True
, asyncio вручную считывает и отправляет файл, если платформа не поддерживает системный вызов sendfile, например, Windows или SSL-сокет в Unix).Вызывается исключение
SendfileNotAvailableError
если система не поддерживает sendfile системный вызов и fallback равенFalse
.sock должен быть неблокирующим сокетом.
Добавлено в версии 3.7.
DNS¶
-
coroutine
loop.
getaddrinfo
(host, port, *, family=0, type=0, proto=0, flags=0)¶ Асинхронная версия
socket.getaddrinfo()
.
-
coroutine
loop.
getnameinfo
(sockaddr, flags=0)¶ Асинхронная версия
socket.getnameinfo()
.
Изменено в версии 3.7: Оба метода getaddrinfo и getnameinfo всегда задокументированы
возвращающие корутину, но до Python 3.7 они фактически возвращали asyncio.Future
объекты. Начиная с Python 3.7 оба методы являются корутинами.
Работа с пайпами¶
-
coroutine
loop.
connect_read_pipe
(protocol_factory, pipe)¶ Регистрация чтения из конца pipe в событийном цикле.
protocol_factory должен быть вызываемым, возвращающим реализацию asyncio протокол.
pipe является файловым объектом.
Возвращается пара
(transport, protocol)
, где transport поддерживает интерфейсReadTransport
, а protocol является экземпляром объекта, создаваемым protocol_factory.При
SelectorEventLoop
цикла событий pipe устанавливается в не блокирующий режим.
-
coroutine
loop.
connect_write_pipe
(protocol_factory, pipe)¶ Регистрация записи в конец pipe в событийного цикла.
protocol_factory должен быть вызываемым, возвращающим реализацию asyncio протокола.
pipe является файловым объектом.
Возвращается пара
(transport, protocol)
, где transport поддерживаетсяWriteTransport
интерфейс и protocol является объектом созданный protocol_factory.С
SelectorEventLoop
событийном цикле, pipe переводится в неблокирующий режим.
Примечание
SelectorEventLoop
не поддерживает вышеуказанные методы в Windows.
Используйте ProactorEventLoop
в Windows.
См.также
Сигналы Unix¶
-
loop.
add_signal_handler
(signum, callback, *args)¶ Устанавливает callback в качестве обработчика сигнала signum.
Коллбэк вызывается loop вместе с другими обратными вызовами в очереди и выполняемыми корутинами этого событийного цикла. В отличие от обработчиков сигналов, зарегистрированных с помощью
signal.signal()
, коллбэк, зарегистрированный с помощью этой функции, может взаимодействовать с событийным циклом.Вызывается исключение
ValueError
, если номер сигнала недействителен или не поддается обработке. ПоднимитеRuntimeError
, если возникла проблема с настройкой обработчика.Используйте
functools.partial()
:ref:` для передачи ключевых аргументов <asyncio-pass-keywords>` для callback.Как и
signal.signal()
, функция должна вызываться в основном потоке.
-
loop.
remove_signal_handler
(sig)¶ Удаляет обработчик сигнала sig.
Возвращает
True
, если обработчик сигнала был удален, илиFalse
, если обработчик для данного сигнала не был установлен.Availability: Unix.
См.также
Модуль signal
.
Выполнение кода в пулах потоков или процессов¶
-
awaitable
loop.
run_in_executor
(executor, func, *args)¶ Организовать вызов func в указанном исполнителе.
Аргумент executor должен быть сущности
concurrent.futures.Executor
. По умолчанию исполнитель используется, если executorNone
.Пример:
import asyncio import concurrent.futures def blocking_io(): # Файловые операции (такие как журналирование) могут блокировать # событийный цикл: запустив их в пуле потоков. with open('/dev/urandom', 'rb') as f: return f.read(100) def cpu_bound(): # Связанные с процессором операции блокируют событийного цикла обработки: # в общем, лучше запускать их в # пул процессов. return sum(i * i for i in range(10 ** 7)) async def main(): loop = asyncio.get_running_loop() ## Опции: # 1. Запустить в исполнителе цикла по умолчанию: result = await loop.run_in_executor( None, blocking_io) print('default thread pool', result) # 2. Запустить в пользовательском пуле потоков: with concurrent.futures.ThreadPoolExecutor() as pool: result = await loop.run_in_executor( pool, blocking_io) print('custom thread pool', result) # 3. Запустить в пользовательском пуле процессов: with concurrent.futures.ProcessPoolExecutor() as pool: result = await loop.run_in_executor( pool, cpu_bound) print('custom process pool', result) asyncio.run(main())
Метод возвращает объект
asyncio.Future
.Используйте
functools.partial()
передача ключевых аргументов для func.Изменено в версии 3.5.3:
loop.run_in_executor()
больше не настраиваетmax_workers
создаваемого исполнителя пула потоков, вместо этого он оставляет его исполнителю пула потоков (ThreadPoolExecutor
) для установки по умолчанию.
-
loop.
set_default_executor
(executor)¶ Установка executor в качестве исполнителя по умолчанию, используемого
run_in_executor()
. executor должно быть сущностьюThreadPoolExecutor
.Не рекомендуется, начиная с версии 3.8: Использование исполнителя, не являющегося сущностью
ThreadPoolExecutor
устарело и вызовет ошибку в Python 3.9.Исполнитель должен быть сущностью класса
concurrent.futures.ThreadPoolExecutor
.
API обработки ошибок¶
Позволяет настроить способ обработки особых ситуаций в событийном цикле.
-
loop.
set_exception_handler
(handler)¶ Устанавливает handler в качестве нового обработчика исключений событийного цикла.
Если handler
None
, будет установлен обработчик исключений по по умолчанию. В противном случае handler должен быть вызываемым с сигнатурным(loop, context)
соответствием, гдеloop
- ссылка на активный событийный цикл, аcontext
- объектdict
, содержащий подробные сведения об исключении (подробнее о контексте см.call_exception_handler()
в документации).
-
loop.
get_exception_handler
()¶ Возвращает текущий обработчик исключений или
None
, если не задан пользовательский обработчик исключений.Добавлено в версии 3.5.2.
-
loop.
default_exception_handler
(context)¶ Обработчик исключения по умолчанию.
Вызывается при возникновении исключения и отсутствии установленного обработчика исключений. Он может быть вызван пользовательским обработчиком исключений, который хочет ожидать поведения обработчика по умолчанию.
Параметр context имеет то же значение, что и
call_exception_handler()
.
-
loop.
call_exception_handler
(context)¶ Вызов текущего обработчика исключений событийного цикла.
context - это объект
dict
, содержащий следующие ключи, которые могут быть добавлены в будущей Python версии)- „message“: сообщение об ошибке;
- „exception“ (опционален): Объект исключения;
- „future“ (опционален):
asyncio.Future
сущность; - „handle“ (опционален):
asyncio.Handle
сущность; - „protocol“ (опционален): Protocol сущность;
- „transport“ (опционален): Transport сущность;
- (Необязательно):
socket.socket
сущность.
Примечание
Этот метод не должен перегружаться в подклассе событийного цикла. Для пользовательской обработки исключений используйте метод
set_exception_handler()
.
Активация возможности режима отладки¶
-
loop.
get_debug
()¶ Получение режима отладки (
bool
) событийного цикла.Значение по умолчанию
True
, если переменная средыPYTHONASYNCIODEBUG
имеет непустую строку,False
в противном случае.
-
loop.
set_debug
(enabled: bool)¶ Устанавливает режим отладки событийного цикла.
Изменено в версии 3.7: Теперь можно использовать также
-X dev
. Новый параметр командной строки используемый для включения режима отладки.
См.также
Управление подпроцессами¶
Методы, описанные в этих подразделах, являются низкоуровневыми. В регулярном
async/await коде принято соглашение о использовании высокоуровневых удобных функций
asyncio.create_subprocess_shell()
и asyncio.create_subprocess_exec()
.
Примечание
Событийный цикл asyncio по умолчанию на Windows не поддерживает подпроцессы. Дополнительные сведения см. в разделе Поддержка подпроцессов в Windows.
-
coroutine
loop.
subprocess_exec
(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶ Создаёт подпроцесс из одного или нескольких строковых аргументов, указанных args.
args должен быть списком строк, представленных
str
;- или
bytes
, закодированные кодировкой файловой системы.
Первый строка указывает исполняемый файл программы, а остальные строки - аргументы. Собранная вместе строка аргументов формирует
argv
программы.Аналогично стандартной библиотеке,
subprocess.Popen
класс называется сshell=False
и списком строк, переданных в качестве первого аргумента; Однако там, гдеPopen
принимает один аргумент, который является списком строк, subprocess_exec принимает несколько строковые аргументы.protocol_factory должен быть вызываемым возвращением подкласс
asyncio.SubprocessProtocol
класса.Другие параметры:
stdin может быть любым из следующих
- файлоподобный объект, представляющий канал для подключения к
стандартному входному потоку подпроцесса с использованием
connect_write_pipe()
- константа
subprocess.PIPE
(по умолчанию), с которой создаётся новый пайп и подключение к уже существующему - значение
None
заставит подпроцесс наследовать дескриптор файла от этого процесса - константу
subprocess.DEVNULL
, указывающую, что будет использоватьсяos.devnull
специальный файл
- файлоподобный объект, представляющий канал для подключения к
стандартному входному потоку подпроцесса с использованием
stdout может быть любым из следующих
- файлоподобный объект, представляющий канал для подключения к
стандартному выходному потоку подпроцесса с использованием
connect_write_pipe()
- константа
subprocess.PIPE
(по умолчанию), с которой создаётся новый пайп и подключение к уже существующему - значение
None
что заставит подпроцесс наследовать дескриптор файла от этого процесса - константу
subprocess.DEVNULL
, указывающую, что будет использоватьсяos.devnull
специальный файл
- файлоподобный объект, представляющий канал для подключения к
стандартному выходному потоку подпроцесса с использованием
stderr может быть любым из следующих
- файлоподобный объект, представляющий канал для подключения к
стандартному потоку ошибок подпроцесса с помощью
connect_write_pipe()
- константа
subprocess.PIPE
(по умолчанию), с которой создаётся новый пайп и подключение к уже существующему - значение
None
что заставит подпроцесс наследовать дескриптор файла от этого процесса - константу
subprocess.DEVNULL
, указывающую, что будет использоватьсяos.devnull
специальный файл - константа
subprocess.STDOUT
, соединяющая стандартый поток ошибок в стандартный выходной поток процесса
- файлоподобный объект, представляющий канал для подключения к
стандартному потоку ошибок подпроцесса с помощью
Все остальные ключевые аргументы передаются
subprocess.Popen
без интерпретации, за исключением bufsize, universal_newlines, shell, text, encoding и errors, которые не следует указывать вообще.API подпроцесса
asyncio
не поддерживает декодирование потоков как текст.bytes.decode()
можно использовать для преобразования возвращаемых байтов из потока в текст.
Документацию по другим аргументам см. в конструкторе класса
subprocess.Popen
.Возвращает пару
(transport, protocol)
, где transport соответствует базовому классуasyncio.SubprocessTransport
, и protocol - объект, наследуемый от protocol_factory.
-
coroutine
loop.
subprocess_shell
(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶ Создаёт подпроцесс из cmd, который может быть
str
илиbytes
закодированной строки кодировки файловой системы, используя шелл синтаксис платформы.Он похож на стандартную библиотеку
subprocess.Popen
класса вызываемого сshell=True
.protocol_factory должен быть вызываемым возвращением подкласс
SubprocessProtocol
класса.Дополнительные сведения об остальных аргументах см. в разделе
subprocess_exec()
.Возвращает пару
(transport, protocol)
, где transport соответствует базовому классуSubprocessTransport
, и protocol - объект, наследуемый от protocol_factory.
Примечание
В обязанности приложения входит обеспечение того, чтобы все пробелы и
специальные символы цитировались надлежащим образом, чтобы избежать уязвимостей
шелл инъекции. Функция
shlex.quote()
может быть используемый для правильного экранирования пробелов и
специальных символов строки, которые будут используемый для создания команд
оболочки.
Обработчики коллбэков¶
-
class
asyncio.
Handle
¶ Коллбэк обёртка, возвращается
loop.call_soon()
,loop.call_soon_threadsafe()
.-
cancel
()¶ Отменит коллбэк. Если коллбэк уже отменен или исполнен, это метод ничего не делает.
-
cancelled
()¶ Возвращает
True
, если коллбэк был отменен.Добавлено в версии 3.7.
-
-
class
asyncio.
TimerHandle
¶ Коллбэк обёртка, возвращенный
loop.call_later()
иloop.call_at()
.Этот класс - подкласс
Handle
.-
when
()¶ Возвращает запланированное время коллбэка в виде
float
секунд.Время является абсолютной меткой времени, использующей одно и то же время как ссылку на
loop.time()
.Добавлено в версии 3.7.
-
Объекты сервера¶
Объекты сервера создаются loop.create_server()
, loop.create_unix_server()
, start_server()
и функцией
start_unix_server()
.
Не создаваёт экземпляры класса напрямую.
-
class
asyncio.
Server
¶ Server объекты являются асинхронными менеджерами контекста. При использовании с
async with
оператором гарантированно, что объект Server закрыт и не принимает новые соединения по завершенииasync with
оператора:srv = await loop.create_server(...) async with srv: # некоторый код # В этот момент srv закрыт и больше не принимает новые подключения.
Изменено в версии 3.7: Объект сервера является асинхронным диспетчером контекста с Python 3.7.
-
close
()¶ Прекращение обслуживания: закрывает прослушивающие сокеты и устанавливает аттрибуту
sockets
значениеNone
.Сокеты, представляющие существующие входящие клиентские подключения остаются открытыми.
Сервер закрывается асинхронно, для этого используйте
wait_closed()
корутину ожидания закрытия сервера.
-
get_loop
()¶ Возвращает событийный цикл, связанный с объектом сервера.
Добавлено в версии 3.7.
-
coroutine
start_serving
()¶ Начало принятия подключений.
Этот метод является идемпотентным, поэтому его можно вызвать, когда сервер уже работает.
Ключевой параметр start_serving для
loop.create_server()
иasyncio.start_server()
позволяет создать объект Server не принимая первоначальных соединений. В этом случаеServer.start_serving()
можно заменить наServer.serve_forever()
чтобы сервер начал принимать подключения.Добавлено в версии 3.7.
-
coroutine
serve_forever
()¶ Начинает принимать соединения до тех пор, пока короутин не будет отменен. Отмена
serve_forever
задачи вызывает закрытие сервера.Этот метод можно вызвать, если сервер уже принимает подключения. Только одна задача
serve_forever
может существовать в одином объекте Server.Пример:
async def client_connected(reader, writer): # Взаимодействие клиента с потоками # читения/записи. Например: await reader.readline() async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) await srv.serve_forever() asyncio.run(main('127.0.0.1', 0))
Добавлено в версии 3.7.
-
is_serving
()¶ Возвращает
True
, если сервер принимает новые подключения.Добавлено в версии 3.7.
-
sockets
¶ Список объектов
socket.socket
, прослушивающих сервер.Изменено в версии 3.7: До Python 3.7
Server.sockets
использовал возвращаемый внутренний список сокетов сервера. В 3.7 копия из возвращаемого списка.
-
Реализация событийного цикла¶
asyncio поставляется с двумя различными реализациями событийного цикла:
SelectorEventLoop
и ProactorEventLoop
.
По умолчанию asyncio настроен на использование SelectorEventLoop
на Unix и
ProactorEventLoop
на Windows.
-
class
asyncio.
SelectorEventLoop
¶ Событийный цикл на основе модуля
selectors
.Использует наиболее эффективные selector, доступный для данной платформы. Также можно вручную настроить точную реализацию для используемого селектора:
import asyncio import selectors selector = selectors.SelectSelector() loop = asyncio.SelectorEventLoop(selector) asyncio.set_event_loop(loop)
Availability: Unix, Windows.
-
class
asyncio.
ProactorEventLoop
¶ Событийный цикл для Windows, использует «порты завершения ввода-вывода» (IOCP).
Availability: Windows.
-
class
asyncio.
AbstractEventLoop
¶ Абстрактный базовый класс для asyncio-compliant событийных циклов.
В методах событийного цикла перечислены все методы, которые должны были быть определены для альтернативной реализации
AbstractEventLoop
.
Примеры¶
Обратите внимание, что все примеры в этом разделе целенаправленно написаны для
использования низкоуровневых API событийного цикла, таких как loop.run_forever()
и
loop.call_soon()
. Современные asyncio приложения редко необходимо написать таким
образом; вместо них рекомендуется использования высокоуровневые функций, например asyncio.run()
.
Hello world с call_soon()¶
Пример использования метод loop.call_soon()
для планирования коллбэков. Коллбэк
отображает "Hello World"
и затем останавливает событийный цикл:
import asyncio
def hello_world(loop):
"""Коллбэк печатает 'Hello World' и останавливает событийный цикл"""
print('Hello World')
loop.stop()
loop = asyncio.get_event_loop()
# Запланировать вызов hello_world()
loop.call_soon(hello_world, loop)
# Блокирующий вызов прерываемый loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См.также
Аналогичный пример Hello World, созданный с помощью корутины
и функции run()
.
Отображение текущей даты с call_later()¶
Пример коллбэка, отображающего текущую дату каждую секунду. Коллбэк
использует loop.call_later()
метод для перепланируется
после 5 секунд, а затем останавливает событийный цикл:
import asyncio
import datetime
def display_date(end_time, loop):
print(datetime.datetime.now())
if (loop.time() + 1.0) < end_time:
loop.call_later(1, display_date, end_time, loop)
else:
loop.stop()
loop = asyncio.get_event_loop()
# Запланировать первый вызов display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
# Блокировка вызова прервана loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См.также
Аналогичный пример current date, созданный с
помощью корутины и функции run()
.
Просмотр дескриптора файла для событий чтения¶
Ожидание, пока файловый дескриптор не получит некоторые данные с помощью
loop.add_reader()
метода и затем закрывает событийный цикл:
import asyncio
from socket import socketpair
# Создаёт пару связанных файловых дескрипторов
rsock, wsock = socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# Мы закончили: отменить регистрацию файлового дескриптора
loop.remove_reader(rsock)
# Отстановить событийный цикл
loop.stop()
# Зарегистрировать дескриптор файла для события чтения
loop.add_reader(rsock, reader)
# Имитировать прием данных из сети
loop.call_soon(wsock.send, 'abc'.encode())
try:
# Запуск событийного цикла
loop.run_forever()
finally:
# Мы сделали. Закройте сокеты и цикл обработки событий.
rsock.close()
wsock.close()
loop.close()
См.также
- Подобно в примерах
с использованием транспортов, протоколов и метода
loop.create_connection()
. - Другой подобный пример
использующий функцию
asyncio.open_connection()
высокого уровня и потоки.
Установка обработчиков сигналов для SIGINT и SIGTERM¶
(Этот signals
пример работает только в Unix.
Регистрация обработчиков сигналов SIGINT
и SIGTERM
применяя метод loop.add_signal_handler()
:
import asyncio
import functools
import os
import signal
def ask_exit(signame, loop):
print("got signal %s: exit" % signame)
loop.stop()
async def main():
loop = asyncio.get_running_loop()
for signame in {'SIGINT', 'SIGTERM'}:
loop.add_signal_handler(
getattr(signal, signame),
functools.partial(ask_exit, signame, loop))
await asyncio.sleep(3600)
print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")
asyncio.run(main())