Петля событий

Код источника: Lib/asyncio/events.py, Lib/asyncio/base_events.py


Предисловие

Цикл событий является ядром любого приложения asyncio. Циклы событий запускают асинхронные задачи и обратные вызовы, выполняют сетевые операции ввода-вывода и запускают подпроцессы.

Разработчики приложений обычно используют высокоуровневые функции asyncio, такие как asyncio.run(), и редко должны ссылаться на объект цикла или вызывать его методы. Этот раздел предназначен в основном для авторов низкоуровневого кода, библиотек и фреймворков, которым необходим более тонкий контроль над поведением цикла событий.

Получение цикла событий

Для получения, установки или создания цикла событий можно использовать следующие низкоуровневые функции:

asyncio.get_running_loop()

Возвращает запущенный цикл событий в текущем потоке ОС.

Вызывает сообщение RuntimeError, если цикл событий не запущен.

Эта функция может быть вызвана только из корутины или обратного вызова.

Added in version 3.7.

asyncio.get_event_loop()

Получите текущий цикл событий.

При вызове из корутины или обратного вызова (например, запланированного с помощью call_soon или аналогичного API) эта функция всегда будет возвращать запущенный цикл событий.

Если цикл событий не установлен, функция вернет результат вызова get_event_loop_policy().get_event_loop().

Поскольку эта функция имеет довольно сложное поведение (особенно при использовании пользовательских политик циклов событий), использование функции get_running_loop() предпочтительнее, чем get_event_loop() в корутинах и обратных вызовах.

Как отмечалось выше, вместо использования этих функций нижнего уровня для ручного создания и закрытия цикла событий следует использовать функцию более высокого уровня asyncio.run().

Не рекомендуется, начиная с версии 3.12: Предупреждение об устаревании выдается, если нет текущего цикла событий. В некоторых будущих версиях Python это станет ошибкой.

asyncio.set_event_loop(loop)

Установите loop в качестве текущего цикла событий для текущего потока ОС.

asyncio.new_event_loop()

Создает и возвращает новый объект цикла событий.

Обратите внимание, что поведение функций get_event_loop(), set_event_loop() и new_event_loop() может быть изменено с помощью setting a custom event loop policy.

Содержание

Эта страница документации содержит следующие разделы:

Методы циклов событий

Циклы событий имеют низкоуровневые API для следующего:

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

loop.run_until_complete(future)

Выполняется до тех пор, пока не завершится будущее (экземпляр Future).

Если аргументом является coroutine object, он неявно запланирован на выполнение как asyncio.Task.

Верните результат выполнения Future или вызовите исключение.

loop.run_forever()

Выполняйте цикл событий до тех пор, пока не будет вызван stop().

Если stop() будет вызван до вызова run_forever(), цикл опросит селектор ввода-вывода один раз с таймаутом, равным нулю, выполнит все обратные вызовы, запланированные в ответ на события ввода-вывода (и те, которые уже были запланированы), и затем выйдет.

Если stop() будет вызван во время выполнения run_forever(), цикл выполнит текущую партию обратных вызовов, а затем выйдет. Обратите внимание, что новые обратные вызовы, запланированные с помощью callbacks, в этом случае не будут запущены; вместо этого они будут запущены при следующем вызове run_forever() или run_until_complete().

loop.stop()

Остановите цикл событий.

loop.is_running()

Возвращает True, если цикл событий в данный момент запущен.

loop.is_closed()

Возвращает True, если цикл событий был закрыт.

loop.close()

Закройте цикл событий.

В момент вызова этой функции цикл не должен быть запущен. Все ожидающие обратные вызовы будут отброшены.

Этот метод очищает все очереди и завершает работу исполнителя, но не ждет его завершения.

Этот метод является идемпотентным и необратимым. Никакие другие методы не должны вызываться после закрытия цикла событий.

coroutine loop.shutdown_asyncgens()

Запланируйте закрытие всех открытых в данный момент объектов asynchronous generator вызовом aclose(). После вызова этого метода цикл событий выдаст предупреждение, если будет итерирован новый асинхронный генератор. Этот метод следует использовать для надежного завершения работы всех запланированных асинхронных генераторов.

Обратите внимание, что нет необходимости вызывать эту функцию, если используется asyncio.run().

Пример:

try:
    loop.run_forever()
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Added in version 3.6.

coroutine loop.shutdown_default_executor(timeout=None)

Запланируйте закрытие стандартного исполнителя и дождитесь, пока он присоединится ко всем потокам в ThreadPoolExecutor. После вызова этого метода использование стандартного исполнителя с loop.run_in_executor() приведет к возникновению RuntimeError.

Параметр timeout задает количество времени (в float секунд), которое дается исполнителю для завершения присоединения. При значении по умолчанию None исполнителю дается неограниченное количество времени.

Если таймаут достигнут, выдается сообщение RuntimeWarning и исполнитель по умолчанию завершается, не дожидаясь окончания объединения потоков.

Примечание

Не вызывайте этот метод при использовании asyncio.run(), так как последний автоматически обрабатывает выключение исполнителя по умолчанию.

Added in version 3.9.

Изменено в версии 3.12: Добавлен параметр timeout.

Планирование обратных вызовов

loop.call_soon(callback, *args, context=None)

Запланируйте вызов callback callback с аргументами args на следующей итерации цикла событий.

Возвращает экземпляр asyncio.Handle, который может быть использован позже для отмены обратного вызова.

Обратные вызовы вызываются в том порядке, в котором они были зарегистрированы. Каждый обратный вызов будет вызван ровно один раз.

Необязательный аргумент context, содержащий только ключевое слово, задает пользовательский contextvars.Context, в котором будет выполняться обратный вызов. Обратные вызовы используют текущий контекст, если не указан context.

В отличие от call_soon_threadsafe(), этот метод не является потокобезопасным.

loop.call_soon_threadsafe(callback, *args, context=None)

Потокобезопасный вариант call_soon(). При планировании обратных вызовов из другого потока эта функция должна использоваться, поскольку call_soon() не является потокобезопасной.

Вызывает RuntimeError, если вызывается в цикле, который был закрыт. Это может произойти во вторичном потоке, когда основное приложение завершает работу.

См. раздел concurrency and multithreading в документации.

Изменено в версии 3.7: Добавлен параметр контекст, который зависит только от ключевого слова. Более подробную информацию см. в разделе PEP 567.

Примечание

Большинство функций планирования asyncio не позволяют передавать аргументы в виде ключевых слов. Для этого используйте functools.partial():

# will schedule "print("Hello", flush=True)"
loop.call_soon(
    functools.partial(print, "Hello", flush=True))

Использование частичных объектов обычно удобнее, чем использование лямбд, поскольку asyncio может лучше отображать частичные объекты в отладочных сообщениях и сообщениях об ошибках.

Планирование отложенных обратных вызовов

Цикл событий предоставляет механизмы для планирования функций обратного вызова, которые должны быть вызваны в определенный момент в будущем. Для отслеживания времени в цикле событий используются монотонные часы.

loop.call_later(delay, callback, *args, context=None)

Запланируйте обратный вызов, который будет вызван через заданное задержку количество секунд (может быть как int, так и float).

Возвращается экземпляр asyncio.TimerHandle, который можно использовать для отмены обратного вызова.

обратный вызов будет вызван ровно один раз. Если два обратных вызова запланированы на одно и то же время, порядок их вызова не определен.

Необязательные позиционные args будут переданы обратному вызову при его вызове. Если вы хотите, чтобы обратный вызов был вызван с аргументами в виде ключевых слов, используйте functools.partial().

Необязательный аргумент context, содержащий только ключевое слово, позволяет указать пользовательский contextvars.Context для запуска callback. Текущий контекст используется, если не указан context.

Изменено в версии 3.7: Добавлен параметр контекст, который зависит только от ключевого слова. Более подробную информацию см. в разделе PEP 567.

Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией цикла событий по умолчанию, задержка не могла превышать одного дня. Это было исправлено в Python 3.8.

loop.call_at(when, callback, *args, context=None)

Запланируйте обратный вызов в заданную абсолютную временную метку когда (int или float), используя ту же временную ссылку, что и loop.time().

Этот метод ведет себя так же, как и call_later().

Возвращается экземпляр asyncio.TimerHandle, который можно использовать для отмены обратного вызова.

Изменено в версии 3.7: Добавлен параметр контекст, который зависит только от ключевого слова. Более подробную информацию см. в разделе 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 (с лучшей производительностью или инструментарием).

Added in version 3.5.2.

loop.create_task(coro, *, name=None, context=None)

Запланируйте выполнение coroutine coro. Возвращает объект Task.

Сторонние циклы событий могут использовать свой собственный подкласс Task для совместимости. В этом случае тип результата является подклассом Task.

Если указан аргумент name, а не None, он устанавливается в качестве имени задачи с помощью Task.set_name().

Необязательный аргумент context, содержащий только ключевое слово, позволяет указать пользовательский contextvars.Context, в котором будет выполняться coro. Если аргумент context не указан, создается копия текущего контекста.

Изменено в версии 3.8: Добавлен параметр name.

Изменено в версии 3.11: Добавлен параметр context.

loop.set_task_factory(factory)

Установите фабрику задач, которая будет использоваться loop.create_task().

Если factory равно None, то будет установлена фабрика задач по умолчанию. В противном случае factory должна быть callable с сигнатурой, соответствующей (loop, coro, context=None), где loop - ссылка на активный цикл событий, а coro - объект coroutine. Вызываемый объект должен возвращать 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, ssl_shutdown_timeout=None, happy_eyeballs_delay=None, interleave=None, all_errors=False)

Открывает потоковое транспортное соединение с заданным адресом, указанным host и port.

Семейство сокетов может быть либо AF_INET, либо AF_INET6 в зависимости от host (или аргумента family, если он указан).

Тип сокета будет SOCK_STREAM.

protocol_factory должен быть вызываемым файлом, возвращающим реализацию asyncio protocol.

Этот метод попытается установить соединение в фоновом режиме. В случае успеха он возвращает пару (transport, protocol).

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

  1. Соединение устанавливается, и для него создается transport.

  2. protocol_factory вызывается без аргументов и, как ожидается, вернет экземпляр protocol.

  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() для разрешения хоста. Если заданы, то все они должны быть целыми числами из соответствующих констант модуля socket.

  • happy_eyeballs_delay, если задано, включает Happy Eyeballs для этого соединения. Это должно быть число с плавающей точкой, представляющее собой количество времени в секундах, которое необходимо потратить на ожидание завершения попытки соединения, прежде чем начинать следующую попытку параллельно. Это «Задержка попытки соединения», как определено в RFC 8305. Разумным значением по умолчанию, рекомендованным RFC, является 0.25 (250 миллисекунд).

  • interleave управляет переупорядочиванием адресов, когда имя хоста разрешается в несколько IP-адресов. Если 0 или не указано, переупорядочивание не производится, и адреса пробуются в порядке, возвращенном getaddrinfo(). Если указано положительное целое число, то адреса чередуются по семействам адресов, и данное целое число интерпретируется как «First Address Family Count», как определено в RFC 8305. По умолчанию используется 0, если happy_eyeballs_delay не задано, и 1, если задано.

  • sock, если указан, должен быть существующим, уже подключенным socket.socket объектом, который будет использоваться транспортом. Если задан sock, то не должны быть указаны host, port, family, proto, flags, happy_eyeballs_delay, interleave и local_addr.

    Примечание

    Аргумент sock передает право собственности на сокет созданному транспорту. Чтобы закрыть сокет, вызовите метод close() транспорта.

  • local_addr, если задан, является кортежем (local_host, local_port), используемым для локальной привязки сокета. Для поиска local_host и local_port используется getaddrinfo(), аналогично host и port.

  • ssl_handshake_timeout - это (для TLS-соединения) время в секундах, в течение которого следует ожидать завершения TLS-гэндшейка перед прерыванием соединения. 60.0 секунд, если None (по умолчанию).

  • ssl_shutdown_timeout - время в секундах, в течение которого необходимо дождаться завершения отключения SSL перед прерыванием соединения. 30.0 секунд, если None (по умолчанию).

  • all_errors определяет, какие исключения будут вызваны, когда соединение не может быть создано. По умолчанию поднимается только одно Exception: первое исключение, если оно одно или все ошибки имеют одинаковое сообщение, или одно OSError с объединенными сообщениями об ошибках. Если all_errors равно True, будет поднят ExceptionGroup, содержащий все исключения (даже если есть только одно).

Изменено в версии 3.5: Добавлена поддержка SSL/TLS в ProactorEventLoop.

Изменено в версии 3.6: Параметр socket socket.TCP_NODELAY устанавливается по умолчанию для всех TCP-соединений.

Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.

Изменено в версии 3.8: Добавлены параметры happy_eyeballs_delay и interleave.

Алгоритм «Счастливые глаза»: Успех с двухстековыми хостами. Когда IPv4-путь и протокол сервера работают, а IPv6-путь и протокол сервера не работают, клиентское приложение с двойным стеком испытывает значительную задержку соединения по сравнению с клиентом, использующим только IPv4. Это нежелательно, поскольку приводит к ухудшению пользовательского опыта клиента двух стеков. Этот документ определяет требования к алгоритмам, которые уменьшают эту видимую пользователем задержку, и предоставляет алгоритм.

Дополнительная информация: https://datatracker.ietf.org/doc/html/rfc6555

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Изменено в версии 3.12: Была добавлена функция all_errors.

См.также

Функция 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_port=None, allow_broadcast=None, sock=None)

Создайте дейтаграммное соединение.

Семейство сокетов может быть либо AF_INET, либо AF_INET6, либо AF_UNIX, в зависимости от host (или аргумента family, если он указан).

Тип сокета будет SOCK_DGRAM.

protocol_factory должен быть вызываемым файлом, возвращающим реализацию protocol.

В случае успеха возвращается кортеж (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() для разрешения хоста. Если заданы, то все они должны быть целыми числами из соответствующих констант модуля socket.

  • reuse_port указывает ядру разрешить этой конечной точке быть привязанной к тому же порту, к которому привязаны другие существующие конечные точки, если все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows и некоторых Unix. Если константа socket.SO_REUSEPORT не определена, то эта возможность не поддерживается.

  • allow_broadcast указывает ядру разрешить этой конечной точке отправлять сообщения на широковещательный адрес.

  • В качестве опции можно указать sock, чтобы использовать уже существующий, подключенный объект socket.socket, который будет использоваться транспортом. Если указано, local_addr и remote_addr должны быть опущены (должны быть None).

    Примечание

    Аргумент sock передает право собственности на сокет созданному транспорту. Чтобы закрыть сокет, вызовите метод close() транспорта.

См. примеры UDP echo client protocol и UDP echo server protocol.

Изменено в версии 3.4.4: Добавлены параметры family, proto, flags, reuse_address, reuse_port, allow_broadcast и sock.

Изменено в версии 3.8: Добавлена поддержка Windows.

Изменено в версии 3.8.1: Параметр reuse_address больше не поддерживается, так как использование socket.SO_REUSEADDR представляет собой серьезную проблему безопасности для UDP. Явная передача reuse_address=True вызовет исключение.

Когда несколько процессов с разными UID назначают сокеты на одинаковый адрес сокета UDP с SO_REUSEADDR, входящие пакеты могут случайным образом распределяться между сокетами.

Для поддерживаемых платформ reuse_port может быть использован в качестве замены аналогичной функциональности. При использовании reuse_port вместо него используется socket.SO_REUSEPORT, что специально предотвращает назначение сокетов на один и тот же адрес сокета процессами с разными UID.

Изменено в версии 3.11: Параметр reuse_address, отключенный в Python 3.8.1, 3.7.6 и 3.6.10, был полностью удален.

coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Создайте соединение Unix.

Семейство сокетов будет AF_UNIX; тип сокета будет SOCK_STREAM.

В случае успеха возвращается кортеж (transport, protocol).

path - это имя сокета домена Unix, которое обязательно, если не указан параметр sock. Поддерживаются абстрактные сокеты Unix, пути str, bytes и Path.

Информацию об аргументах этого метода см. в документации метода loop.create_connection().

Availability: Unix.

Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout. Параметр path теперь может быть path-like object.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Создание сетевых серверов

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, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)

Создайте TCP-сервер (тип сокета SOCK_STREAM), прослушивающий порт адреса хоста.

Возвращает объект Server.

Аргументы:

  • protocol_factory должен быть вызываемым файлом, возвращающим реализацию protocol.

  • Параметр host может быть задан несколькими типами, которые определяют, где будет прослушиваться сервер:

    • Если host - строка, то TCP-сервер привязывается к одному сетевому интерфейсу, указанному host.

    • Если host - это последовательность строк, то TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в этой последовательности.

    • Если host - пустая строка или None, предполагаются все интерфейсы, и будет возвращен список из нескольких сокетов (скорее всего, один для IPv4 и другой для IPv6).

  • Параметр port может быть задан для указания порта, который должен прослушивать сервер. Если задано значение 0 или None (по умолчанию), будет выбран случайный неиспользуемый порт (обратите внимание, что если host разрешается на несколько сетевых интерфейсов, для каждого интерфейса будет выбран свой случайный порт).

  • family может быть установлено в socket.AF_INET или AF_INET6, чтобы заставить сокет использовать IPv4 или IPv6. Если значение не задано, семейство будет определяться по имени хоста (по умолчанию AF_UNSPEC).

  • flags - это битовая маска для getaddrinfo().

  • В качестве опции можно указать sock, чтобы использовать уже существующий объект сокета. Если указано, то host и port не должны быть указаны.

    Примечание

    Аргумент sock передает право собственности на сокет созданному серверу. Чтобы закрыть сокет, вызовите метод close() сервера.

  • backlog - это максимальное количество соединений в очереди, переданное в listen() (по умолчанию равно 100).

  • ssl можно установить в значение SSLContext, чтобы включить TLS для принимаемых соединений.

  • reuse_address указывает ядру повторно использовать локальный сокет в состоянии TIME_WAIT, не дожидаясь истечения его естественного таймаута. Если не указано, автоматически устанавливается в True на Unix.

  • reuse_port указывает ядру разрешить этой конечной точке быть привязанной к тому же порту, к которому привязаны другие существующие конечные точки, если все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows.

  • keep_alive, установленное в True, поддерживает соединения активными, позволяя периодически передавать сообщения.

Изменено в версии 3.13: Добавлен параметр keep_alive.

  • ssl_handshake_timeout - это (для TLS-сервера) время в секундах, в течение которого необходимо дождаться завершения TLS-хендшейка перед прерыванием соединения. 60.0 секунд, если None (по умолчанию).

  • ssl_shutdown_timeout - время в секундах, в течение которого необходимо дождаться завершения отключения SSL перед прерыванием соединения. 30.0 секунд, если None (по умолчанию).

  • start_serving, установленное в True (по умолчанию), заставляет созданный сервер немедленно начать принимать соединения. Если установлено значение False, пользователь должен дождаться Server.start_serving() или Server.serve_forever(), чтобы сервер начал принимать соединения.

Изменено в версии 3.5: Добавлена поддержка SSL/TLS в ProactorEventLoop.

Изменено в версии 3.5.1: Параметр host может быть последовательностью строк.

Изменено в версии 3.6: Добавлены параметры ssl_handshake_timeout и start_serving. Параметр socket socket.TCP_NODELAY устанавливается по умолчанию для всех TCP-соединений.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

См.также

Функция 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, ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)

Аналогичен loop.create_server(), но работает с семейством сокетов AF_UNIX.

path - это имя сокета домена Unix, и оно обязательно, если не указан аргумент sock. Поддерживаются абстрактные сокеты Unix, пути str, bytes и Path.

Если значение cleanup_socket равно true, то сокет Unix будет автоматически удален из файловой системы при закрытии сервера, если только сокет не был заменен после создания сервера.

Информацию об аргументах этого метода см. в документации метода loop.create_server().

Availability: Unix.

Изменено в версии 3.7: Добавлены параметры ssl_handshake_timeout и start_serving. Параметр path теперь может быть объектом Path.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Изменено в версии 3.13: Добавлен параметр cleanup_socket.

coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Оберните уже принятое соединение в пару транспорт/протокол.

Этот метод может использоваться серверами, которые принимают соединения вне asyncio, но используют asyncio для их обработки.

Параметры:

  • protocol_factory должен быть вызываемым файлом, возвращающим реализацию protocol.

  • sock - это уже существующий объект сокета, возвращенный из socket.accept.

    Примечание

    Аргумент sock передает право собственности на сокет созданному транспорту. Чтобы закрыть сокет, вызовите метод close() транспорта.

  • Значение ssl может быть установлено в SSLContext, чтобы включить SSL для принимаемых соединений.

  • ssl_handshake_timeout - это (для SSL-соединения) время в секундах, в течение которого следует ожидать завершения SSL-квитирования перед прерыванием соединения. 60.0 секунд, если None (по умолчанию).

  • ssl_shutdown_timeout - время в секундах, в течение которого необходимо дождаться завершения отключения SSL перед прерыванием соединения. 30.0 секунд, если None (по умолчанию).

Возвращает пару (transport, protocol).

Added in version 3.5.3.

Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Передача файлов

coroutine loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)

Отправить файл по транспорту. Возвращает общее количество отправленных байт.

Метод использует высокопроизводительные os.sendfile(), если они доступны.

file должен быть обычным файловым объектом, открытым в бинарном режиме.

offset указывает, с какого места начинать чтение файла. Если указано, count - это общее количество байтов, которое нужно передать, а не отправлять файл до достижения EOF. Позиция файла всегда обновляется, даже если этот метод приводит к ошибке, и file.tell() может быть использован для получения фактического количества переданных байт.

Значение fallback, установленное в True, заставляет asyncio вручную читать и отправлять файл, если платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет на Unix).

Вызывает SendfileNotAvailableError, если система не поддерживает системный вызов sendfile и fallback равен False.

Added in version 3.7.

Обновление TLS

coroutine loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Обновление существующего соединения на основе транспорта до TLS.

Создайте экземпляр кодера/декодера TLS и вставьте его между транспортом и протоколом. Кодер/декодер реализует как протокол, обращенный к транспорту, так и транспорт, обращенный к протоколу.

Возвращает созданный двухинтерфейсный экземпляр. После await протокол должен прекратить использование исходного транспорта и взаимодействовать с возвращенным объектом только потому, что кодер кэширует протокольные данные и спорадически обменивается с транспортом дополнительными пакетами TLS-сессии.

В некоторых ситуациях (например, когда переданный транспорт уже закрывается) это может вернуть None.

Параметры:

  • экземпляры транспорта и протокола, которые возвращают такие методы, как create_server() и create_connection().

  • sslcontext: сконфигурированный экземпляр SSLContext.

  • server_side передайте True, когда обновляется соединение на стороне сервера (например, созданное с помощью create_server()).

  • server_hostname: задает или переопределяет имя хоста, по которому будет сопоставляться сертификат целевого сервера.

  • ssl_handshake_timeout - это (для TLS-соединения) время в секундах, в течение которого следует ожидать завершения TLS-гэндшейка перед прерыванием соединения. 60.0 секунд, если None (по умолчанию).

  • ssl_shutdown_timeout - время в секундах, в течение которого необходимо дождаться завершения отключения SSL перед прерыванием соединения. 30.0 секунд, если None (по умолчанию).

Added in version 3.7.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

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

loop.add_reader(fd, callback, *args)

Начните отслеживать файловый дескриптор fd на предмет доступности для чтения и вызовите callback с указанными аргументами, как только fd станет доступен для чтения.

loop.remove_reader(fd)

Прекращает мониторинг файлового дескриптора fd на доступность для чтения. Возвращает True, если fd ранее отслеживался на предмет чтения.

loop.add_writer(fd, callback, *args)

Запускает мониторинг файлового дескриптора fd на предмет доступности для записи и вызывает callback с указанными аргументами, как только fd становится доступным для записи.

Используйте functools.partial() to pass keyword arguments для обратного вызова.

loop.remove_writer(fd)

Прекращает мониторинг файлового дескриптора fd на предмет доступности записи. Возвращает True, если fd ранее отслеживался на предмет записи.

О некоторых ограничениях этих методов см. также раздел Platform Support.

Работа с объектами сокетов напрямую

В целом, реализации протоколов, использующие транспортные API, такие как loop.create_connection() и loop.create_server(), быстрее, чем реализации, работающие с сокетами напрямую. Однако есть случаи, когда производительность не критична, а работа с объектами socket напрямую более удобна.

coroutine loop.sock_recv(sock, nbytes)

Получение до nbytes от sock. Асинхронная версия socket.recv().

Возвращает полученные данные в виде объекта bytes.

sock должен быть неблокирующим сокетом.

Изменено в версии 3.7: Несмотря на то, что этот метод всегда документировался как метод coroutine, релизы до Python 3.7 возвращали Future. Начиная с Python 3.7 этот метод является методом async def.

coroutine loop.sock_recv_into(sock, buf)

Получение данных из sock в буфер buf. Моделируется на основе блокирующего метода socket.recv_into().

Возвращает количество байт, записанных в буфер.

sock должен быть неблокирующим сокетом.

Added in version 3.7.

coroutine loop.sock_recvfrom(sock, bufsize)

Получение дейтаграммы размером до bufsize от sock. Асинхронная версия socket.recvfrom().

Возвращает кортеж из (полученные данные, удаленный адрес).

sock должен быть неблокирующим сокетом.

Added in version 3.11.

coroutine loop.sock_recvfrom_into(sock, buf, nbytes=0)

Получение дейтаграммы размером до nbytes из sock в buf. Асинхронная версия socket.recvfrom_into().

Возвращает кортеж из (количество полученных байт, удаленный адрес).

sock должен быть неблокирующим сокетом.

Added in version 3.11.

coroutine loop.sock_sendall(sock, data)

Отправка данных на сокет sock. Асинхронная версия socket.sendall().

Этот метод продолжает отправлять данные на сокет до тех пор, пока не будут отправлены все данные в data или не произойдет ошибка. В случае успеха возвращается None. При ошибке вызывается исключение. Кроме того, нет способа определить, сколько данных, если таковые имеются, было успешно обработано принимающей стороной соединения.

sock должен быть неблокирующим сокетом.

Изменено в версии 3.7: Несмотря на то, что метод всегда документировался как метод корутины, до Python 3.7 он возвращал значение Future. Начиная с Python 3.7, это метод async def.

coroutine loop.sock_sendto(sock, data, address)

Отправка дейтаграммы с sock на address. Асинхронная версия socket.sendto().

Возвращает количество отправленных байтов.

sock должен быть неблокирующим сокетом.

Added in version 3.11.

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.

См.также

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 должен быть неблокирующим сокетом.

Added in version 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)

Зарегистрируйте конец чтения трубы в цикле событий.

protocol_factory должен быть вызываемым файлом, возвращающим реализацию asyncio protocol.

труба - это file-like object.

Возвращает пару (transport, protocol), где transport поддерживает интерфейс ReadTransport, а protocol является объектом, инстанцированным protocol_factory.

При использовании цикла событий SelectorEventLoop труба переводится в неблокирующий режим.

coroutine loop.connect_write_pipe(protocol_factory, pipe)

Зарегистрируйте конец записи трубы в цикле событий.

protocol_factory должен быть вызываемым файлом, возвращающим реализацию asyncio protocol.

труба - это file-like object.

Возвращает пару (transport, protocol), где transport поддерживает интерфейс WriteTransport, а protocol является объектом, инстанцированным protocol_factory.

При использовании цикла событий SelectorEventLoop труба переводится в неблокирующий режим.

Примечание

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() to pass keyword arguments для обратного вызова.

Как и 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():
    # 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)

if __name__ == '__main__':
    asyncio.run(main())

Обратите внимание, что защита точки входа (if __name__ == '__main__') требуется для варианта 3 из-за особенностей multiprocessing, который используется ProcessPoolExecutor. См. Safe importing of main module.

Этот метод возвращает объект asyncio.Future.

Используйте functools.partial() to pass keyword arguments для функции.

Изменено в версии 3.5.3: loop.run_in_executor() больше не настраивает max_workers создаваемого им исполнителя пула потоков, оставляя за исполнителем пула потоков (ThreadPoolExecutor) право устанавливать значение по умолчанию.

loop.set_default_executor(executor)

Установите executor в качестве исполнителя по умолчанию, используемого run_in_executor(). executor должен быть экземпляром ThreadPoolExecutor.

Изменено в версии 3.11: исполнитель должен быть экземпляром ThreadPoolExecutor.

API для обработки ошибок

Позволяет настроить обработку исключений в цикле событий.

loop.set_exception_handler(handler)

Установите handler в качестве нового обработчика исключений цикла событий.

Если handler имеет значение None, будет установлен обработчик исключений по умолчанию. В противном случае handler должен быть вызываемым объектом с сигнатурой, соответствующей (loop, context), где loop - ссылка на активный цикл событий, а context - объект dict, содержащий детали исключения (подробности о контексте см. в документации call_exception_handler()).

Если обработчик вызывается от имени Task или Handle, он запускается в contextvars.Context этой задачи или хэндла обратного вызова.

Изменено в версии 3.12: Обработчик может быть вызван в Context задачи или обработчика, в котором возникло исключение.

loop.get_exception_handler()

Возвращает текущий обработчик исключений или None, если пользовательский обработчик исключений не был установлен.

Added in version 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 экземпляр;

  • „task“ (необязательно): asyncio.Task экземпляр;

  • „handle“ (необязательно): asyncio.Handle экземпляр;

  • „protocol“ (необязательно): Protocol экземпляр;

  • „transport“ (необязательно): Transport экземпляр;

  • „socket“ (необязательно): socket.socket экземпляр;

  • „asyncgen“ (необязательно): Асинхронный генератор, который вызвал

    исключение.

Примечание

Этот метод не должен перегружаться в подклассах циклов событий. Для пользовательской обработки исключений используйте метод set_exception_handler().

Включение режима отладки

loop.get_debug()

Получение режима отладки (bool) цикла событий.

Значение по умолчанию - True, если переменная окружения PYTHONASYNCIODEBUG имеет значение непустой строки, False - в противном случае.

loop.set_debug(enabled: bool)

Установите режим отладки цикла событий.

Изменено в версии 3.7: Новый Python Development Mode теперь также может быть использован для включения режима отладки.

loop.slow_callback_duration

Этот атрибут можно использовать для установки минимальной продолжительности выполнения в секундах, которая считается «медленной». Когда включен режим отладки, «медленные» обратные вызовы будут записываться в журнал.

Значение по умолчанию - 100 миллисекунд.

См.также

В этом списке debug mode of asyncio.

Запуск подпроцессов

Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном коде async/await вместо них используйте высокоуровневые удобные функции asyncio.create_subprocess_shell() и asyncio.create_subprocess_exec().

Примечание

В Windows стандартный цикл событий ProactorEventLoop поддерживает подпроцессы, а SelectorEventLoop - нет. Подробности см. в разделе Subprocess Support on 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 может быть любым из них:

    • файлоподобный объект

    • существующий дескриптор файла (целое положительное число), например, созданный с помощью os.pipe().

    • константа subprocess.PIPE (по умолчанию), которая создаст новую трубу и соединит ее,

    • значение None, которое заставит подпроцесс унаследовать дескриптор файла от данного процесса

    • константа subprocess.DEVNULL, которая указывает, что будет использоваться специальный файл os.devnull

  • stdout может быть любым из этих вариантов:

    • файлоподобный объект

    • константа subprocess.PIPE (по умолчанию), которая создаст новую трубу и соединит ее,

    • значение None, которое заставит подпроцесс унаследовать дескриптор файла от данного процесса

    • константа subprocess.DEVNULL, которая указывает, что будет использоваться специальный файл os.devnull

  • stderr может быть любым из них:

    • файлоподобный объект

    • константа subprocess.PIPE (по умолчанию), которая создаст новую трубу и соединит ее,

    • значение None, которое заставит подпроцесс унаследовать дескриптор файла от данного процесса

    • константа subprocess.DEVNULL, которая указывает, что будет использоваться специальный файл os.devnull

    • константа subprocess.STDOUT, которая соединит стандартный поток ошибок со стандартным потоком вывода процесса

  • Все остальные ключевые аргументы передаются в subprocess.Popen без интерпретации, за исключением bufsize, universal_newlines, shell, text, encoding и errors, которые вообще не следует указывать.

    API подпроцесса asyncio не поддерживает декодирование потоков в текст. bytes.decode() может быть использован для преобразования байтов, возвращаемых из потока, в текст.

Если файлоподобный объект, переданный как stdin, stdout или stderr, представляет собой трубу, то другая сторона этой трубы должна быть зарегистрирована как connect_write_pipe() или connect_read_pipe() для использования в цикле событий.

Документацию по другим аргументам см. в конструкторе класса 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, закодированной в filesystem encoding, используя синтаксис «shell» платформы.

Это похоже на то, как в стандартной библиотеке subprocess.Popen класс вызывается с помощью shell=True.

Фабрика protocol_factory должна быть вызываемым элементом, возвращающим подкласс класса SubprocessProtocol.

Более подробную информацию об остальных аргументах см. в разделе subprocess_exec().

Возвращает пару (transport, protocol), где transport соответствует базовому классу SubprocessTransport, а protocol - объект, инстанцированный фабрикой protocol_factory.

Примечание

Во избежание уязвимостей shell injection приложение обязано убедиться, что все пробельные и специальные символы заключены в кавычки должным образом. Функция shlex.quote() может быть использована для правильной экранировки пробельных и специальных символов в строках, которые будут использоваться для создания команд оболочки.

Обратные вызовы

class asyncio.Handle

Объект-обертка обратного вызова, возвращаемый loop.call_soon(), loop.call_soon_threadsafe().

get_context()

Возвращает объект contextvars.Context, связанный с хэндлом.

Added in version 3.12.

cancel()

Отмена обратного вызова. Если обратный вызов уже был отменен или выполнен, этот метод не имеет эффекта.

cancelled()

Возвращает True, если обратный вызов был отменен.

Added in version 3.7.

class asyncio.TimerHandle

Объект-обертка обратного вызова, возвращаемый loop.call_later() и loop.call_at().

Этот класс является подклассом класса Handle.

when()

Возвращает запланированное время обратного вызова в виде float секунд.

Время - это абсолютная временная метка, использующая ту же временную привязку, что и loop.time().

Added in version 3.7.

Объекты сервера

Объекты сервера создаются функциями loop.create_server(), loop.create_unix_server(), start_server() и start_unix_server().

Не инстанцируйте класс 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.

Изменено в версии 3.11: В Python 3.9.11, 3.10.3 и 3.11 этот класс был публично раскрыт как asyncio.Server.

close()

Прекратите обслуживание: закройте прослушивающие сокеты и установите атрибут sockets в None.

Сокеты, представляющие существующие входящие клиентские соединения, остаются открытыми.

Сервер закрывается асинхронно; используйте корутину wait_closed(), чтобы дождаться, пока сервер будет закрыт (и больше не будет активных соединений).

close_clients()

Закройте все существующие входящие клиентские соединения.

Вызывает close() на всех связанных транспортах.

close() следует вызывать перед close_clients() при закрытии сервера, чтобы избежать скачков при подключении новых клиентов.

Added in version 3.13.

abort_clients()

Немедленно закрывайте все существующие входящие клиентские соединения, не дожидаясь завершения ожидающих операций.

Вызывает abort() на всех связанных транспортах.

close() следует вызывать перед abort_clients() при закрытии сервера, чтобы избежать скачков при подключении новых клиентов.

Added in version 3.13.

get_loop()

Возвращает цикл событий, связанный с объектом сервера.

Added in version 3.7.

coroutine start_serving()

Начните принимать соединения.

Этот метод является идемпотентным, поэтому его можно вызывать, когда сервер уже обслуживается.

Параметр start_serving, относящийся только к ключевому слову loop.create_server() и asyncio.start_server(), позволяет создать объект Server, который изначально не принимает соединения. В этом случае Server.start_serving() или Server.serve_forever() можно использовать для того, чтобы сервер начал принимать соединения.

Added in version 3.7.

coroutine serve_forever()

Начните принимать соединения до тех пор, пока не будет отменена эта корутина. Отмена задачи serve_forever приводит к закрытию сервера.

Этот метод может быть вызван, если сервер уже принимает соединения. На один объект Server может существовать только одна задача serve_forever.

Пример:

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

Added in version 3.7.

is_serving()

Возвращает True, если сервер принимает новые соединения.

Added in version 3.7.

coroutine wait_closed()

Дождитесь завершения работы метода close() и завершения всех активных соединений.

sockets

Список сокет-подобных объектов, asyncio.trsock.TransportSocket, которые прослушивает сервер.

Изменено в версии 3.7: До Python 3.7 Server.sockets возвращала внутренний список серверных сокетов напрямую. В версии 3.7 возвращается копия этого списка.

Реализации циклов событий

asyncio поставляется с двумя различными реализациями циклов событий: SelectorEventLoop и ProactorEventLoop.

По умолчанию asyncio настроен на использование EventLoop.

class asyncio.SelectorEventLoop

Подкласс AbstractEventLoop, основанный на модуле selectors.

Использует наиболее эффективный селектор, доступный для данной платформы. Также можно вручную настроить точную реализацию селектора, который будет использоваться:

import asyncio
import selectors

class MyPolicy(asyncio.DefaultEventLoopPolicy):
   def new_event_loop(self):
      selector = selectors.SelectSelector()
      return asyncio.SelectorEventLoop(selector)

asyncio.set_event_loop_policy(MyPolicy())

Availability: Unix, Windows.

class asyncio.ProactorEventLoop

Подкласс AbstractEventLoop для Windows, использующий «порты завершения ввода-вывода» (IOCP).

Availability: Windows.

class asyncio.EventLoop

Псевдоним наиболее эффективного доступного подкласса AbstractEventLoop для данной платформы.

Это псевдоним SelectorEventLoop в Unix и ProactorEventLoop в Windows.

Added in version 3.13.

class asyncio.AbstractEventLoop

Абстрактный базовый класс для Asyncio-совместимых циклов событий.

В разделе Методы циклов событий перечислены все методы, которые должны быть определены в альтернативной реализации 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):
    """A callback to print 'Hello World' and stop the event loop"""
    print('Hello World')
    loop.stop()

loop = asyncio.new_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()

См.также

Аналогичный пример Hello World, созданный с помощью coroutine и функции 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.new_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()

См.также

Аналогичный пример current date, созданный с помощью coroutine и функции run().

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

Дождитесь, пока файловый дескриптор получит некоторые данные с помощью метода loop.add_reader(), а затем закройте цикл событий:

import asyncio
from socket import socketpair

# Create a pair of connected file descriptors
rsock, wsock = socketpair()

loop = asyncio.new_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()

См.также

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