Цикл обработки событий
Исходный код: Lib/asyncio/events.py, Lib/asyncio/base_events.py
Преамбула
Цикл обработки событий является ядром каждого приложения asyncio. Циклы обработки событий выполняют асинхронные задачи и обратные вызовы, выполняют операции ввода-вывода сети и запускают подпроцессы.
Разработчики приложений обычно должны использовать функции asyncio высокого уровня, такие как asyncio.run(), и им редко нужно обращаться к объекту цикла или вызывать его методы. Этот раздел предназначен в основном для авторов кода, библиотек и фреймворков низкого уровня, которым требуется более тонкий контроль над поведением цикла обработки событий.
Получение цикла обработки событий
Для получения, установки или создания цикла обработки событий можно использовать следующие функции низкого уровня:
-
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() может быть изменено с помощью установки пользовательской политики цикла обработки событий.
Содержание
Эта страница документации содержит следующие разделы:
- Раздел Методы цикла обработки событий — справочная документация по API цикла обработки событий;
- Раздел Обработка обратных вызовов содержит документацию по экземплярам
HandleиTimerHandle, возвращаемым методами планирования, такими какloop.call_soon()иloop.call_later(); - Раздел Объекты сервера содержит документацию по типам, возвращаемым методами цикла обработки событий, такими как
loop.create_server(); - Раздел Реализации цикла обработки событий содержит документацию по классам
SelectorEventLoopиProactorEventLoop; - Раздел Примеры демонстрирует работу с некоторыми API цикла обработки событий.
Методы цикла событий
Циклы событий имеют низкоуровневые API для следующих задач:
- Запуск и остановка цикла
- Планирование обратных вызовов
- Планирование отложенных обратных вызовов
- Создание объектов Future и Task
- Открытие сетевых подключений
- Создание сетевых серверов
- Передача файлов
- Обновление TLS
- Наблюдение за дескрипторами файлов
- Работа с объектами сокетов напрямую
- DNS
- Работа с каналами
- Сигналы Unix
- Выполнение кода в пулах потоков или процессов
- API обработки ошибок
- Включение отладочного режима
- Запуск дочерних процессов
Запуск и остановка цикла
-
loop.run_until_complete(future) -
Запуск до завершения future (экземпляр
Future).Если аргументом является объект корутины, он неявно планируется для выполнения как
asyncio.Task.Возвращает результат Future или поднимает его исключение.
-
loop.run_forever() -
Запуск цикла событий до вызова
stop().Если
stop()вызывается доrun_forever(), цикл проверит селектор ввода-вывода один раз с таймаутом 0, выполнит все обратные вызовы, запланированные в ответ на события ввода-вывода (и те, что уже были запланированы), и затем завершится.Если
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():
# will schedule "print("Hello", flush=True)"
loop.call_soon(
functools.partial(print, "Hello", flush=True))
Использование объектов partial обычно удобнее, чем использование лямбда-выражений, поскольку asyncio может лучше отображать объекты partial в сообщениях отладки и об ошибках.
Планирование отложенных обратных вызовов
Цикл событий предоставляет механизмы для планирования обратных вызовов функций, которые должны быть вызваны в какой-то момент в будущем. Цикл событий использует монотонные часы для отслеживания времени.
-
loop.call_later(delay, callback, *args, context=None) -
Планирует вызов callback после заданного delay количества секунд (может быть целым или дробным числом).
Возвращается экземпляр
asyncio.TimerHandle, который может использоваться для отмены обратного вызова.callback будет вызван ровно один раз. Если два обратных вызова запланированы на одно и то же время, порядок их вызова не определён.
Необязательные позиционные 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) -
Планирует вызов callback в заданный абсолютный момент времени when (целое или дробное число), используя ту же систему отсчёта времени, что и
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().
Создание объектов Future и Tasks
-
loop.create_future() -
Создаёт объект
asyncio.Future, привязанный к циклу событий.Это предпочтительный способ создания объектов 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, этот контекст используется для создания транспорта; если ssl равноTrue, используется контекст по умолчанию, возвращаемый из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вызовет исключение.Когда несколько процессов с различными идентификаторами пользователей назначают сокеты идентичному адресу UDP-соккета с
SO_REUSEADDR, входящие пакеты могут случайным образом распределяться между сокетами.Для поддерживаемых платформ reuse_port может быть использован в качестве замены для аналогичной функциональности. С reuse_port вместо
SO_REUSEPORTиспользуется, что специально предотвращает назначение сокетов процессами с разными идентификаторами пользователей одному адресу сокета.Создать подключение дейтаграм.
Семейство сокета может быть
AF_INET,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; тип сокета будетSOCK_STREAM.В случае успеха возвращается кортеж
(transport, protocol).path — имя Unix-доменного сокета и является обязательным, за исключением случаев, когда указан параметр sock. Поддерживаются абстрактные Unix-сокеты, пути типа
str,bytesиPath.Для получения информации об аргументах этого метода см. документацию метода
loop.create_connection().Доступность: 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. Поддерживаются абстрактные сокеты Unix, пути
str,bytesиPath.Обратитесь к документации метода
loop.create_server()за информацией об аргументах этого метода.Доступность: 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 — существующий объект сокета, возвращенный методом
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 — общее количество байтов для передачи, а не передача файла до достижения конца файла. Положение файла всегда обновляется, даже если метод вызывает ошибку, и
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 перед прерыванием соединения.
60.0секунд, еслиNone(по умолчанию).
В версии 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().Возвращает полученные данные как объект bytes.
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попытается проверить, уже ли разрешен адрес, вызвавsocket.inet_pton(). Если нет, будет использованloop.getaddrinfo()для разрешения адреса.См. также
-
coroutine loop.sock_accept(sock) -
Принять соединение. Моделируется по блокирующему методу
socket.accept().Сокет должен быть привязан к адресу и слушать соединения. Результат — пара
(conn, address)где conn — новый сокет, используемый для отправки и получения данных по соединению, а 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_STREAMsocket.file должен быть регулярным объектом файла, открытым в двоичном режиме.
offset указывает, с какой позиции начать чтение файла. Если указано, count — общее количество байтов для передачи, а не отправка файла до достижения конца файла. Позиция файла всегда обновляется, даже когда этот метод вызывает ошибку, и
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.В цикле событий типа
SelectorEventLooppipe устанавливается в режим без блокировки.
-
coroutine loop.connect_write_pipe(protocol_factory, pipe) -
Регистрация выходного конца pipe в цикле событий.
protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.
pipe — объект, подобный файлу.
Возвращает пару
(transport, protocol), где transport поддерживает интерфейсWriteTransport, а protocol — объект, созданный protocol_factory.В цикле событий типа
SelectorEventLooppipe устанавливается в режим без блокировки.
Примечание
SelectorEventLoop не поддерживает указанные методы в Windows. Используйте ProactorEventLoop для Windows.
См. также
Сигналы Unix
-
loop.add_signal_handler(signum, callback, *args) -
Устанавливает callback в качестве обработчика сигнала signum.
Обработчик вызывается циклом loop вместе с другими запланированными обработчиками и выполняемыми корутинами этого цикла событий. В отличие от обработчиков сигналов, зарегистрированных с помощью
signal.signal(), обработчик, зарегистрированный этой функцией, может взаимодействовать с циклом событий.Возникает
ValueError, если номер сигнала некорректен или не может быть перехвачен. ВозникаетRuntimeError, если возникла проблема при настройке обработчика.Используйте
functools.partial()для передачи аргументов по ключу в callback.Как и
signal.signal(), эта функция должна вызываться в основном потоке.
-
loop.remove_signal_handler(sig) -
Удаляет обработчик сигнала sig.
Возвращает
Trueесли обработчик сигнала был удален, илиFalseесли для данного сигнала не был установлен обработчик.Доступность: Unix.
См. также
Модуль signal.
Выполнение кода в пулах потоков или процессов
-
awaitable loop.run_in_executor(executor, func, *args) -
Организует вызов func в указанном исполнителе.
Аргумент executor должен быть экземпляром
concurrent.futures.Executor. Используется исполнителем по умолчанию, если executor равенNone.Пример:
import asyncio import concurrent.futures def blocking_io(): # File operations (such as logging) can block the # event loop: run them in a thread pool. with open('/dev/urandom', 'rb') as f: return f.read(100) def cpu_bound(): # CPU-bound operations will block the event loop: # in general it is preferable to run them in a # process pool. return sum(i * i for i in range(10 ** 7)) async def main(): loop = asyncio.get_running_loop() ## Options: # 1. Run in the default loop's executor: result = await loop.run_in_executor( None, blocking_io) print('default thread pool', result) # 2. Run in a custom thread pool: with concurrent.futures.ThreadPoolExecutor() as pool: result = await loop.run_in_executor( pool, blocking_io) print('custom thread pool', result) # 3. Run in a custom process pool: 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.executor должен быть экземпляром
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’ (необязательно): Объект протокола;
- ‘transport’ (необязательно): Объект транспорта;
- ‘socket’ (необязательно): Объект
socket.socket.
Примечание
Этот метод не должен переопределяться в подклассах циклов событий. Для пользовательской обработки исключений используйте метод
set_exception_handler().
Включение отладочного режима
-
loop.get_debug() -
Получить отладочный режим (с типом
bool) цикла событий.Значение по умолчанию —
Trueесли переменная средыPYTHONASYNCIODEBUGустановлена в непустую строку,Falseв противном случае.
-
loop.set_debug(enabled: bool) -
Установить отладочный режим цикла событий.
Изменено в версии 3.7: Новый параметр командной строки
-X devтеперь также может использоваться для включения отладочного режима.
См. также
Режим отладки asyncio.
Запуск дочерних процессов
Методы, описанные в этом разделе, являются низкоуровневыми. В обычном коде 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: # some code # At this point, srv is closed and no longer accepts new connections.Изменено в версии 3.7: Объект Server является асинхронным контекстным менеджером с 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): # Communicate with the client with # reader/writer streams. For example: 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.
-
coroutine wait_closed() -
Дождитесь завершения метода
close().
-
sockets -
Список объектов
socket.socket, на которых сервер прослушивает подключения.Изменено в версии 3.7: До Python 3.7
Server.socketsвозвращал внутренний список сокетов сервера напрямую. В версии 3.7 возвращается копия этого списка.
-
Реализации циклов событий
asyncio поставляется с двумя различными реализациями циклов событий: SelectorEventLoop и ProactorEventLoop.
По умолчанию asyncio настроен на использование SelectorEventLoop на Unix и ProactorEventLoop на Windows.
-
class asyncio.SelectorEventLoop -
Цикл событий, основанный на модуле
selectors.Использует наиболее эффективный селектор, доступный для данной платформы. Также можно вручную настроить точную реализацию селектора, которую следует использовать:
import asyncio import selectors selector = selectors.SelectSelector() loop = asyncio.SelectorEventLoop(selector) asyncio.set_event_loop(loop)
Доступность: Unix, Windows.
-
class asyncio.ProactorEventLoop -
Цикл событий для Windows, использующий «порты завершения ввода-вывода» (IOCP).
Доступность: Windows.
-
class asyncio.AbstractEventLoop -
Абстрактный базовый класс для циклов событий, совместимых с asyncio.
В разделе «Методы цикла событий» перечислены все методы, которые должна определить альтернативная реализация
AbstractEventLoop.
Примеры
Обратите внимание, что все примеры в этом разделе намеренно демонстрируют использование API низкоуровневой событийной петли, таких как loop.run_forever() и loop.call_soon(). Современные приложения asyncio редко требуют такого написания; рассмотрите использование высокоуровневых функций, таких как asyncio.run().
Привет, мир с call_soon()
Пример использования метода loop.call_soon() для планирования обратного вызова. Обратный вызов отображает "Hello World" и затем останавливает событийную петлю:
import asyncio
def hello_world(loop):
"""A callback to print 'Hello World' and stop the event loop"""
print('Hello World')
loop.stop()
loop = asyncio.get_event_loop()
# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример Привет, мир, созданный с помощью корутины и функции 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()
# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример текущей даты, созданный с помощью корутины и функции run().
Отслеживание дескриптора файла на события чтения
Ожидание, пока дескриптор файла получит данные, используя метод loop.add_reader(), а затем закрытие событийной петли:
import asyncio
from socket import socketpair
# Create a pair of connected file descriptors
rsock, wsock = socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# We are done: unregister the file descriptor
loop.remove_reader(rsock)
# Stop the event loop
loop.stop()
# Register the file descriptor for read event
loop.add_reader(rsock, reader)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
try:
# Run the event loop
loop.run_forever()
finally:
# We are done. Close sockets and the event loop.
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())
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/asyncio-eventloop.html