Событийный цикл

Исходный код: 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 для следующего:

Запуск и остановка цикла

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

Хронологический обзор основной операции выглядит следующим образом:

  1. Установление соединения и для него создается транспорт.
  2. Вызывается protocol_factory без аргументов с ожиданием возвращения сущности протокола.
  3. Сущность протокола связывается с транспортом путем вызова его connection_made() метода.
  4. При успехе возвращается кортеж (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 вызовет исключение.

Если несколько процессов с различными 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.

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.

Наблюдение за файловыми дескрипторами

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 метод.

См.также

loop.create_server() и start_server().

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.

См.также

loop.subprocess_exec() и loop.subprocess_shell() методы.

Сигналы 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. По умолчанию исполнитель используется, если executor None.

Пример:

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 должен быть списком строк, представленных

Первый строка указывает исполняемый файл программы, а остальные строки - аргументы. Собранная вместе строка аргументов формирует 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.

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.

Использует наиболее эффективные 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()

См.также

Установка обработчиков сигналов для 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())