Цикл обработки событий
Исходный код: Lib/asyncio/events.py, Lib/asyncio/base_events.py
Предисловие
Цикл обработки событий — это ядро каждого приложения asyncio. Циклы обработки событий запускают асинхронные задачи и обратные вызовы, выполняют операции ввода-вывода сети и запускают подпроцессы.
Разработчики приложений обычно должны использовать функции asyncio высокого уровня, такие как asyncio.run(), и им редко нужно ссылаться на объект цикла или вызывать его методы. Этот раздел предназначен в основном для авторов кода, библиотек и фреймворков низкого уровня, которым требуется более тонкий контроль над поведением цикла обработки событий.
Получение цикла обработки событий
Следующие функции низкого уровня могут быть использованы для получения, установки или создания цикла обработки событий:
-
asyncio.get_running_loop() -
Возвращает работающий цикл обработки событий в текущей потоке ОС.
Вызывает
RuntimeError, если нет работающего цикла обработки событий.Эту функцию можно вызывать только из корутины или обратного вызова.
Введено в версии 3.7.
-
asyncio.get_event_loop() -
Получает текущий цикл обработки событий.
При вызове из корутины или обратного вызова (например, запланированного с помощью call_soon или аналогичного API) эта функция всегда возвращает работающий цикл обработки событий.
Если нет установленного работающего цикла обработки событий, функция вернёт результат вызова
get_event_loop_policy().get_event_loop().Поскольку эта функция имеет довольно сложное поведение (особенно при использовании пользовательских политик цикла обработки событий), использование функции
get_running_loop()предпочтительнее, чемget_event_loop()в корутинах и обратных вызовах.Как отмечалось выше, следует рассмотреть возможность использования функции высокого уровня
asyncio.run()вместо использования этих функций низкого уровня для ручного создания и закрытия цикла обработки событий.Примечание
В версиях Python 3.10.0–3.10.8 и 3.11.0 эта функция (и другие функции, которые используют её неявно) выводила
DeprecationWarning, если не было работающего цикла обработки событий, даже если текущий цикл был установлен в политике. В версиях Python 3.10.9, 3.11.1 и 3.12 они выводятDeprecationWarning, если нет работающего цикла обработки событий и нет установленного текущего цикла. В какой-то будущей версии Python это станет ошибкой.
-
asyncio.set_event_loop(loop) -
Устанавливает loop в качестве текущего цикла обработки событий для текущей потоке ОС.
-
asyncio.new_event_loop() -
Создаёт и возвращает новый объект цикла обработки событий.
Обратите внимание, что поведение функций get_event_loop(), set_event_loop() и new_event_loop() может быть изменено путём установки пользовательской политики цикла обработки событий.
Содержание
Данная страница документации содержит следующие разделы:
- Раздел Методы цикла обработки событий — это справочная документация по API циклов обработки событий;
- Раздел Обработчики обратных вызовов документирует экземпляры
HandleиTimerHandle, которые возвращаются из методов планирования, таких какloop.call_soon()иloop.call_later(); - Раздел Объекты сервера документирует типы, возвращаемые из методов цикла обработки событий, таких как
loop.create_server(); - Раздел Реализации циклов обработки событий документирует классы
SelectorEventLoopиProactorEventLoop; - Раздел Примеры демонстрирует работу с некоторыми API цикла обработки событий.
Методы цикла событий
Циклы событий имеют низкоуровневые API для следующего:
- Запуск и остановка цикла
- Планирование обратных вызовов
- Планирование отложенных обратных вызовов
- Создание объектов Future и Tasks
- Открытие сетевых соединений
- Создание сетевых серверов
- Передача файлов
- Обновление TLS
- Отслеживание дескрипторов файлов
- Работа с объектами сокетов напрямую
- DNS
- Работа с каналами
- Сигналы Unix
- Выполнение кода в пулах потоков или процессов
- API обработки ошибок
- Включение отладочного режима
- Запуск дочерних процессов
Запуск и остановка цикла
-
loop.run_until_complete(future) -
Запуск до завершения future (экземпляра
Future).Если аргумент является объектом корутины, он неявно планируется для запуска как
asyncio.Task.Возвращает результат Future или поднимает его исключение.
-
loop.run_forever() -
Запуск цикла событий до вызова
stop().Если
stop()вызывается доrun_forever(), цикл проверит селектор ввода/вывода один раз с таймаутом ноль, выполнит все обратные вызовы, запланированные в ответ на события ввода/вывода (и те, которые были запланированы ранее), а затем завершится.Если
stop()вызывается во время работыrun_forever(), цикл выполнит текущую партию обратных вызовов и затем завершится. Обратите внимание, что новые обратные вызовы, запланированные обратными вызовами, в этом случае не будут выполнены; вместо этого они будут выполнены в следующий раз, когда будет вызванrun_forever()илиrun_until_complete().
-
loop.stop() -
Остановка цикла событий.
-
loop.is_running() -
Возвращает
Trueесли цикл событий в данный момент запущен.
-
loop.is_closed() -
Возвращает
Trueесли цикл событий был закрыт.
-
loop.close() -
Закрытие цикла событий.
Цикл не должен быть запущен, когда эта функция вызывается. Все ожидающие обратные вызовы будут проигнорированы.
Этот метод очищает все очереди и завершает исполнителя, но не ждет завершения исполнителя.
Этот метод идемпотентен и необратим. После закрытия цикла событий другие методы вызывать нельзя.
-
coroutine loop.shutdown_asyncgens() -
Планирует закрытие всех открытых в данный момент объектов асинхронного генератора с помощью вызова
aclose(). После вызова этого метода цикл событий будет выдавать предупреждение, если новый асинхронный генератор итерируется. Это необходимо для надёжной финализации всех запланированных асинхронных генераторов.Обратите внимание, что нет необходимости вызывать эту функцию, когда используется
asyncio.run().Пример:
try: loop.run_forever() finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()Введено в версии 3.6.
-
coroutine loop.shutdown_default_executor() -
Планирует закрытие исполнителя по умолчанию и ждёт, пока он присоединит все потоки в
ThreadPoolExecutor. После вызова этого метода использование исполнителя по умолчанию сloop.run_in_executor()вызоветRuntimeError.Примечание
Не вызывайте этот метод при использовании
asyncio.run(), так как последний автоматически обрабатывает закрытие исполнителя по умолчанию.Введено в версии 3.9.
Планирование обратных вызовов
-
loop.call_soon(callback, *args, context=None) -
Планирует вызов callback обратного вызова с аргументами args на следующей итерации цикла событий.
Возвращает экземпляр
asyncio.Handle, который можно использовать позже для отмены обратного вызова.Обратные вызовы вызываются в порядке их регистрации. Каждый обратный вызов будет вызван ровно один раз.
Необязательный ключевой аргумент context задает пользовательский
contextvars.Contextдля выполнения callback. Обратные вызовы используют текущий контекст, если context не указан.В отличие от
call_soon_threadsafe(), этот метод не потокобезопасен.
-
loop.call_soon_threadsafe(callback, *args, context=None) -
Потокобезопасная версия
call_soon(). При планировании обратных вызовов из другого потока необходимо использовать эту функцию, так какcall_soon()не потокобезопасна.Возбуждает
RuntimeError, если вызывается для цикла, который был закрыт. Это может произойти во вторичном потоке, когда основное приложение завершается.См. раздел конкурентности и многопоточности документации.
Изменено в версии 3.7: Добавлен ключевой параметр context. См. 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) -
Запланировать вызов callback через заданное количество delay секунд (может быть целым или дробным числом).
Возвращается экземпляр
asyncio.TimerHandle, который можно использовать для отмены обратного вызова.callback будет вызван ровно один раз. Если два обратных вызова запланированы ровно на одно и то же время, порядок их вызова не определён.
Дополнительные позиционные аргументы args будут переданы обратному вызову при его вызове. Если вы хотите, чтобы обратный вызов вызывался с именованными аргументами, используйте
functools.partial().Необязательный ключевой аргумент context позволяет указать пользовательский
contextvars.Contextдля выполнения callback. Текущий контекст используется, если context не указан.Изменено в версии 3.7: Добавлен ключевой параметр context. Подробнее см. PEP 567.
Изменено в версии 3.8: В Python 3.7 и ранее с реализацией цикла событий по умолчанию значение delay не могло превышать один день. Эта проблема исправлена в Python 3.8.
-
loop.call_at(when, callback, *args, context=None) -
Запланировать вызов callback в заданный абсолютный момент времени when (целое или дробное число), используя ту же временную отметку, что и
loop.time().Поведение этого метода такое же, как у
call_later().Возвращается экземпляр
asyncio.TimerHandle, который можно использовать для отмены обратного вызова.Изменено в версии 3.7: Добавлен ключевой параметр context. Подробнее см. PEP 567.
Изменено в версии 3.8: В Python 3.7 и ранее разница между when и текущим временем не могла превышать один день. Эта проблема исправлена в Python 3.8.
-
loop.time() -
Возвращает текущее время как значение
floatпо внутренним монотонным часам цикла событий.
Примечание
Изменено в версии 3.8: В Python 3.7 и ранее таймауты (относительный delay или абсолютный when) не должны превышать один день. Эта проблема исправлена в Python 3.8.
См. также
Функцию asyncio.sleep().
Создание будущих задач
-
loop.create_future() -
Создаёт объект
asyncio.Future, привязанный к циклу событий.Это предпочтительный способ создания объектов Future в asyncio. Это позволяет сторонним циклам событий предоставлять альтернативные реализации объекта Future (с лучшей производительностью или инструментированием).
Добавлена в версии 3.5.2.
-
loop.create_task(coro, *, name=None) -
Планирует выполнение корутины coro. Возвращает объект
Task.Сторонние циклы событий могут использовать свой собственный подкласс
Taskдля межплатформенной совместимости. В этом случае тип результата является подклассомTask.Если аргумент name предоставлен и не
None, он устанавливается как имя задачи с использованиемTask.set_name().Изменено в версии 3.8: Добавлен параметр name.
-
loop.set_task_factory(factory) -
Устанавливает фабрику задач, которая будет использоваться
loop.create_task().Если factory
Noneустанавливается стандартная фабрика задач. В противном случае, factory должен быть вызываемым с подписью, соответствующей(loop, coro), где loop — ссылка на активный цикл событий, а coro — объект корутины. Вызываемый объект должен возвращать объект, совместимый сasyncio.Future.
-
loop.get_task_factory() -
Возвращает фабрику задач или
Noneесли используется стандартная.
Открытие сетевых соединений
-
coroutine loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None) -
Открывает соединение со стерильным потоком с указанным адресом, заданным host и port.
Семейство сокетов может быть либо
AF_INET, либоAF_INET6в зависимости от host (или аргумента family, если он задан).Тип сокета будет
SOCK_STREAM.protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.
Этот метод попытается установить соединение в фоновом режиме. При успехе он возвращает пару
(transport, protocol).Хронологический обзор базовой операции:
- Соединение устанавливается, и для него создаётся транспорт.
- protocol_factory вызывается без аргументов и ожидается, что он вернёт экземпляр протокола.
- Экземпляр протокола связывается с транспортом путём вызова его метода
connection_made(). - В случае успеха возвращается кортеж
(transport, protocol).
Созданный транспорт представляет собой двунаправленный поток, реализация которого зависит от реализации.
Другие аргументы:
-
ssl: если задан и не равен false, создаётся транспорт 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.Примечание
Аргумент sock передаёт владение сокетом созданному транспорту. Для закрытия сокета вызовите метод
close()транспорта. -
local_addr, если задан, является кортежем
(local_host, local_port), используемым для привязки сокета локально. local_host и local_port ищутся с помощьюgetaddrinfo(), аналогично host и port. -
ssl_handshake_timeout (для TLS-соединения) — время в секундах ожидания завершения рукопожатия TLS перед прерыванием соединения.
60.0секунд, еслиNone(по умолчанию).
Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop.Изменено в версии 3.6: Опция сокета
TCP_NODELAYпо умолчанию устанавливается для всех TCP-соединений.Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.
Изменено в версии 3.8: Добавлены параметры happy_eyeballs_delay и interleave.
Алгоритм Happy Eyeballs: Успех с хостами с двойной адресацией. Когда рабочие IPv4 путь и протокол сервера, но не работают IPv6 путь и протокол сервера, приложение с клиентом с двойной адресацией испытывает значительную задержку соединения по сравнению с клиентом только с IPv4. Это нежелательно, так как заставляет клиента с двойной адресацией иметь худший пользовательский опыт. Этот документ определяет требования к алгоритмам, которые уменьшают эту видимую для пользователя задержку, и предоставляет алгоритм.
Дополнительная информация: https://tools.ietf.org/html/rfc6555
См. также
Функция
open_connection()— это высокоуровневый альтернативный API. Она возвращает пару (StreamReader,StreamWriter), которые можно использовать непосредственно в коде async/await.
-
coroutine loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None) -
Примечание
Параметр reuse_address больше не поддерживается, так как использование
SO_REUSEADDRпредставляет значительную угрозу безопасности для UDP. Явное указаниеreuse_address=Trueвызовет исключение.Когда несколько процессов с разными идентификаторами пользователей назначают сокеты одному и тому же адресу UDP-соккета с
SO_REUSEADDR, входящие пакеты могут случайно распределяться между сокетами.Для поддерживаемых платформ, reuse_port может быть использован в качестве замены для аналогичной функциональности. С reuse_port,
SO_REUSEPORTиспользуется вместо этого, что специально предотвращает назначение сокетов процессами с различными идентификаторами пользователей одному и тому же адресу сокета.Создать подключение датаграмм.
Семейство сокетов может быть либо
AF_INET,AF_INET6, илиAF_UNIX, в зависимости от host (или аргумента family, если он указан).Тип сокета будет
SOCK_DGRAM.protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
В случае успеха возвращается кортеж
(transport, protocol).Другие аргументы:
-
local_addr, если указан, представляет собой кортеж
(local_host, local_port), используемый для привязки сокета локально. local_host и local_port ищутся с помощьюgetaddrinfo(). -
remote_addr, если указан, представляет собой кортеж
(remote_host, remote_port), используемый для подключения сокета к удалённому адресу. remote_host и remote_port ищутся с помощьюgetaddrinfo(). -
family, proto, flags — необязательные семейство адресов, протокол и флаги, которые будут переданы в
getaddrinfo()для разрешения host. Если указаны, они должны быть целыми числами из соответствующих констант модуляsocket. -
reuse_port сообщает ядру, что этот конечный пункт может быть привязан к тому же порту, что и другие существующие конечные пункты, при условии, что все они установили этот флаг при создании. Этот параметр не поддерживается в Windows и некоторых Unix-системах. Если константа
SO_REUSEPORTне определена, эта возможность не поддерживается. - allow_broadcast сообщает ядру, что этот конечный пункт может отправлять сообщения на адрес широковещательной рассылки.
-
sock может быть указан, чтобы использовать уже существующий, подключённый
socket.socketобъект, который будет использоваться транспортом. Если он указан, local_addr и remote_addr должны быть пропущены (должны бытьNone).Примечание
Аргумент sock передает владение сокетом созданному транспорту. Чтобы закрыть сокет, вызовите метод транспорта
close().
См. примеры протокола клиента эха UDP и протокола сервера эха UDP.
Изменено в версии 3.4.4: Были добавлены параметры family, proto, flags, reuse_address, reuse_port, *allow_broadcast и sock.
Изменено в версии 3.8.1: Параметр reuse_address больше не поддерживается из-за проблем безопасности.
Изменено в версии 3.8: Добавлена поддержка Windows.
-
local_addr, если указан, представляет собой кортеж
-
coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None) -
Создать подключение по Unix-доменному сокету.
Семейство сокетов будет
AF_UNIX; тип сокета будетSOCK_STREAM.В случае успеха возвращается кортеж
(transport, protocol).path — имя Unix-доменного сокета, и оно обязательно, если не указан параметр sock. Поддерживаются абстрактные Unix-сокеты, пути
str,bytes, иPath.См. документацию метода
loop.create_connection()для информации об аргументах этого метода.Доступность: Unix.
Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout. Параметр 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) для прослушивания на адресе хоста по порту.Возвращает объект
Server.Аргументы:
- protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
-
Параметр host может принимать несколько типов, определяющих, где будет прослушивать сервер:
- Если host — строка, TCP-сервер привязывается к одному сетевому интерфейсу, указанному в host.
- Если host — последовательность строк, TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в последовательности.
- Если host — пустая строка или
None, предполагаются все интерфейсы, и будет возвращён список нескольких сокетов (скорее всего, один для IPv4 и другой для IPv6).
- Параметр port можно использовать для указания порта, на котором сервер должен прослушивать. Если
0илиNone(по умолчанию), будет выбран случайный свободный порт (обратите внимание, что если host разрешается на несколько сетевых интерфейсов, для каждого интерфейса будет выбран другой случайный порт). -
family можно установить в
socket.AF_INETилиAF_INET6для принудительного использования IPv4 или IPv6 сокета. Если не указано, family определяется по имени хоста (по умолчаниюAF_UNSPEC). -
flags — битовая маска для
getaddrinfo(). -
sock можно указать для использования существующего объекта сокета. Если указано, host и port не должны указываться.
Примечание
Аргумент sock передает владение сокетом создаваемому серверу. Для закрытия сокета вызовите метод
close()сервера. -
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.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop.Изменено в версии 3.5.1: Параметр host может быть последовательностью строк.
Изменено в версии 3.6: Добавлены параметры ssl_handshake_timeout и start_serving. Параметр сокета
TCP_NODELAYустанавливается по умолчанию для всех TCP-соединений.См. также
Функция
start_server()— это альтернативный API высокого уровня, который возвращает паруStreamReaderиStreamWriter, которые могут использоваться в коде async/await.
-
coroutine loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True) -
Аналогично
loop.create_server(), но работает с семейством сокетовAF_UNIX.path — имя сокета Unix-домена, и требуется, если не указан аргумент sock. Поддерживаются пути к абстрактным сокетам Unix,
str,bytesиPath.См. документацию метода
loop.create_server()для получения информации об аргументах этого метода.Доступность: Unix.
Изменено в версии 3.7: Добавлены параметры ssl_handshake_timeout и start_serving. Параметр path теперь может быть объектом
Path.
-
coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None) -
Оборачивает уже принятое соединение в пару транспорт/протокол.
Этот метод может использоваться серверами, которые принимают подключения вне asyncio, но используют asyncio для их обработки.
Параметры:
- protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
-
sock — существующий объект сокета, возвращаемый из
socket.accept.Примечание
Аргумент sock передает владение сокетом создаваемому транспорту. Для закрытия сокета вызовите метод
close()транспорта. -
ssl может быть установлен на
SSLContextдля включения SSL для принятых подключений. -
ssl_handshake_timeout (для SSL-соединения) — время в секундах, которое нужно ждать завершения рукопожатия SSL, прежде чем прервать соединение.
60.0секунд, еслиNone(по умолчанию).
Возвращает пару
(transport, protocol).Введено в версии 3.5.3.
Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.
Передача файлов
-
coroutine loop.sendfile(transport, file, offset=0, count=None, *, fallback=True) -
Передаёт файл через транспорт. Возвращает общее количество переданных байтов.
Метод использует высокопроизводительный
os.sendfile(), если доступен.file должен быть объектом файла, открытым в двоичном режиме.
offset указывает, с какого места начать чтение файла. Если указано, count — общее количество байтов для передачи, а не передача файла до достижения конца файла. Позиция файла всегда обновляется, даже если этот метод генерирует ошибку, и можно использовать
file.tell()для получения фактического количества переданных байтов.fallback установленное в
True, заставляет asyncio вручную читать и отправлять файл, когда платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет в Unix).Вызывает
SendfileNotAvailableError, если система не поддерживает системный вызов sendfile и fallback равноFalse.Введено в версии 3.7.
TLS-совместимое обновление
-
coroutine loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None) -
Обновление существующего транспортного соединения до TLS.
Создаёт экземпляр кодера/декодера TLS и вставляет его между transport и protocol. Кодер/декодер реализует протокол, ориентированный на transport, и транспорт, ориентированный на protocol.
Возвращает созданный экземпляр с двумя интерфейсами. После await, protocol должен перестать использовать исходный transport и взаимодействовать только с возвращённым объектом, так как кодер кэширует данные со стороны protocol и периодически обменивается дополнительными пакетами сессии TLS с transport.
В некоторых ситуациях (например, когда переданный транспорт уже закрывается), это может вернуть
None.Параметры:
- экземпляры transport и protocol, которые возвращают методы, такие как
create_server()иcreate_connection(). - sslcontext: настроенный экземпляр
SSLContext. - server_side передать
Trueпри обновлении серверного соединения (например, созданногоcreate_server()). - server_hostname: устанавливает или переопределяет имя хоста, с которым будет сравниваться сертификат целевого сервера.
- ssl_handshake_timeout (для TLS-соединения) — время в секундах ожидания завершения рукопожатия TLS перед прерыванием соединения.
60.0секунд, еслиNone(по умолчанию).
Добавлена в версии 3.7.
- экземпляры transport и protocol, которые возвращают методы, такие как
Отслеживание дескрипторов файлов
-
loop.add_reader(fd, callback, *args) -
Начать мониторинг дескриптора файла fd на доступность для чтения и вызвать callback со специфицированными аргументами, как только fd станет доступным для чтения.
-
loop.remove_reader(fd) -
Остановить мониторинг дескриптора файла fd на доступность для чтения. Возвращает
Trueесли fd ранее отслеживался на чтение.
-
loop.add_writer(fd, callback, *args) -
Начать мониторинг дескриптора файла fd на доступность для записи и вызвать callback со специфицированными аргументами, как только fd станет доступным для записи.
Используйте
functools.partial()для передачи аргументов по ключевым словам в callback.
-
loop.remove_writer(fd) -
Остановить мониторинг дескриптора файла fd на доступность для записи. Возвращает
Trueесли fd ранее отслеживался на запись.
См. также раздел Поддержка платформ для некоторых ограничений этих методов.
Работа с объектами сокетов напрямую
В целом, реализации протоколов, которые используют транспортные API, такие как loop.create_connection() и loop.create_server(), быстрее, чем реализации, работающие напрямую с сокетами. Однако существуют некоторые случаи, когда производительность некритична, и работа с socket объектами напрямую более удобна.
-
coroutine loop.sock_recv(sock, nbytes) -
Получение до nbytes байтов из sock. Асинхронная версия
socket.recv().Возвращает полученные данные в виде объекта байтов.
sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Несмотря на то, что этот метод всегда документировался как метод сопрограммы, версии до Python 3.7 возвращали
Future. С Python 3.7 это методasync def.
-
coroutine loop.sock_recv_into(sock, buf) -
Получение данных из sock в буфер buf. Моделируется по блокирующему методу
socket.recv_into().Возвращает количество байтов, записанных в буфер.
sock должен быть неблокирующим сокетом.
Добавлена в версии 3.7.
-
coroutine loop.sock_sendall(sock, data) -
Отправка data по сокету sock. Асинхронная версия
socket.sendall().Этот метод продолжает отправку данных по сокету до тех пор, пока все данные в data не будут отправлены или не произойдёт ошибка. При успехе возвращается
None. При ошибке генерируется исключение. Кроме того, нет способа определить, сколько данных, если таковые имеются, было успешно обработано получающей стороной соединения.sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Несмотря на то, что метод всегда документировался как метод сопрограммы, до Python 3.7 он возвращал
Future. С Python 3.7, это методasync def.
-
coroutine loop.sock_connect(sock, address) -
Подключение sock к удалённому сокету по адресу address.
Асинхронная версия
socket.connect().sock должен быть неблокирующим сокетом.
Изменено в версии 3.5.2:
addressбольше не нужно разрешать.sock_connectбудет пытаться проверить, уже ли разрешен адрес, вызвавsocket.inet_pton(). Если нет, будет использоватьсяloop.getaddrinfo()для разрешения адреса.См. также
-
coroutine loop.sock_accept(sock) -
Приём соединения. Моделируется по блокирующему методу
socket.accept().Сокет должен быть привязан к адресу и слушать соединения. Результат — пара
(conn, address), где conn — новый объект сокета, используемый для отправки и приёма данных по соединению, а address — адрес, привязанный к сокету на другом конце соединения.sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Несмотря на то, что метод всегда документировался как метод сопрограммы, до Python 3.7 он возвращал
Future. С Python 3.7, это методasync def.См. также
-
coroutine loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True) -
Отправка файла с помощью высокопроизводительной функции
os.sendfile, если возможно. Возвращает общее количество отправленных байтов.Асинхронная версия
socket.sendfile().sock должен быть неблокирующим
socket.SOCK_STREAMsocket.file должен быть объектом обычного файла, открытым в двоичном режиме.
offset указывает, с какого места начать чтение файла. Если задано, count — это общее количество байтов для передачи, в отличие от отправки файла до достижения EOF. Позиция файла всегда обновляется, даже когда этот метод вызывает ошибку, и
file.tell()может быть использован для получения фактического количества отправленных байтов.fallback, если установлено в
True, заставляет asyncio вручную читать и отправлять файл, когда платформа не поддерживает вызов sendfile (например, Windows или SSL-сокет на Unix).Вызывает
SendfileNotAvailableError, если система не поддерживает вызов sendfile, а fallback равноFalse.sock должен быть неблокирующим сокетом.
Добавлена в версии 3.7.
DNS
-
coroutine loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0) -
Асинхронная версия
socket.getaddrinfo().
-
coroutine loop.getnameinfo(sockaddr, flags=0) -
Асинхронная версия
socket.getnameinfo().
Изменено в версии 3.7: Оба метода getaddrinfo и getnameinfo всегда были задокументированы как возвращающие корутину, но до Python 3.7 они фактически возвращали объекты asyncio.Future. Начиная с Python 3.7 оба метода являются корутинами.
Работа с каналами
-
coroutine loop.connect_read_pipe(protocol_factory, pipe) -
Регистрация входного конца канала pipe в цикле событий.
protocol_factory должен быть вызываемым, возвращающим реализацию протокола asyncio.
pipe — это объект, подобный файлу.
Возвращается пара
(transport, protocol), где transport поддерживает интерфейсReadTransport, а protocol — это объект, созданный protocol_factory.С циклом событий
SelectorEventLoop, канал pipe устанавливается в режим без ожидания.
-
coroutine loop.connect_write_pipe(protocol_factory, pipe) -
Регистрация выходного конца канала pipe в цикле событий.
protocol_factory должен быть вызываемым, возвращающим реализацию протокола asyncio.
pipe — это объект, подобный файлу.
Возвращается пара
(transport, protocol), где transport поддерживает интерфейсWriteTransport, а protocol — это объект, созданный protocol_factory.С циклом событий
SelectorEventLoop, канал pipe устанавливается в режим без ожидания.
Примечание
SelectorEventLoop не поддерживает указанные выше методы в Windows. Используйте ProactorEventLoop для Windows.
См. также
Сигналы Unix
-
loop.add_signal_handler(signum, callback, *args) -
Устанавливает callback в качестве обработчика сигнала signum.
Обработчик будет вызван циклом loop вместе с другими очередями обработчиков и запущенными корутинами этого цикла событий. В отличие от обработчиков сигналов, зарегистрированных с помощью
signal.signal(), обработчик, зарегистрированный этой функцией, может взаимодействовать с циклом событий.Вызовет
ValueError, если номер сигнала недопустимый или неперехватываемый. ВызоветRuntimeError, если возникла проблема с установкой обработчика.Используйте
functools.partial()для передачи аргументов по ключевым словам в callback.Как и
signal.signal(), эта функция должна вызываться в главном потоке.
-
loop.remove_signal_handler(sig) -
Удаляет обработчик сигнала sig.
Возвращает
Trueесли обработчик сигнала был удалён, илиFalseесли для данного сигнала не было установлено никакого обработчика.Доступность: Unix.
См. также
Модуль signal.
Выполнение кода в пулах потоков или процессов
-
awaitable loop.run_in_executor(executor, func, *args) -
Организует вызов func в указанном исполнителе.
Аргумент executor должен быть экземпляром
concurrent.futures.Executor. Используется исполнителем по умолчанию, если executor равенNone.Пример:
import asyncio import concurrent.futures def blocking_io(): # File operations (such as logging) can block the # event loop: run them in a thread pool. with open('/dev/urandom', 'rb') as f: return f.read(100) def cpu_bound(): # CPU-bound operations will block the event loop: # in general it is preferable to run them in a # process pool. return sum(i * i for i in range(10 ** 7)) async def main(): loop = asyncio.get_running_loop() ## Options: # 1. Run in the default loop's executor: result = await loop.run_in_executor( None, blocking_io) print('default thread pool', result) # 2. Run in a custom thread pool: with concurrent.futures.ThreadPoolExecutor() as pool: result = await loop.run_in_executor( pool, blocking_io) print('custom thread pool', result) # 3. Run in a custom process pool: with concurrent.futures.ProcessPoolExecutor() as pool: result = await loop.run_in_executor( pool, cpu_bound) print('custom process pool', result) if __name__ == '__main__': asyncio.run(main())Обратите внимание, что точка входа защиты (
if __name__ == '__main__') необходима для варианта 3 из-за особенностейmultiprocessing, который используетсяProcessPoolExecutor. См. Безопасный импорт главного модуля.Этот метод возвращает объект
asyncio.Future.Используйте
functools.partial()для передачи аргументов по ключевым словам в func.Изменено в версии 3.5.3:
loop.run_in_executor()больше не настраиваетmax_workersисполнителя пула потоков, который он создает, а вместо этого оставляет это за исполнителем пула потоков (ThreadPoolExecutor) для установки по умолчанию.
-
loop.set_default_executor(executor) -
Устанавливает executor в качестве исполнителя по умолчанию, используемого
run_in_executor(). executor должен быть экземпляромThreadPoolExecutor.Устарело начиная с версии 3.8: Использование исполнителя, не являющегося экземпляром
ThreadPoolExecutor, устарело и вызовет ошибку в Python 3.9.executor должен быть экземпляром
concurrent.futures.ThreadPoolExecutor.
Обработка ошибок API
Позволяет настроить обработку исключений в цикле событий.
-
loop.set_exception_handler(handler) -
Устанавливает handler в качестве нового обработчика исключений цикла событий.
Если handler равен
None, будет установлен обработчик исключений по умолчанию. В противном случае, handler должен быть вызываемым объектом с сигнатурой, соответствующей(loop, context), гдеloop— ссылка на активный цикл событий, аcontext— объектdictсодержащий детали исключения (см. документациюcall_exception_handler()для подробностей о контексте).
-
loop.get_exception_handler() -
Возвращает текущий обработчик исключений или
None, если пользовательский обработчик исключений не был установлен.Добавлена в версии 3.5.2.
-
loop.default_exception_handler(context) -
Обработчик исключений по умолчанию.
Вызывается при возникновении исключения, если обработчик исключений не задан. Его также может вызвать пользовательский обработчик исключений для перенаправления обработки к поведению обработчика по умолчанию.
Параметр context имеет то же значение, что и в
call_exception_handler().
-
loop.call_exception_handler(context) -
Вызывает текущий обработчик исключений цикла событий.
context — объект
dictсодержащий следующие ключи (новые ключи могут быть добавлены в будущих версиях Python):- ‘message’: Сообщение об ошибке;
- ‘exception’ (необязательно): Объект исключения;
- ‘future’ (необязательно): Экземпляр
asyncio.Future; - ‘task’ (необязательно): Экземпляр
asyncio.Task; - ‘handle’ (необязательно): Экземпляр
asyncio.Handle; - ‘protocol’ (необязательно): Экземпляр Протокола;
- ‘transport’ (необязательно): Экземпляр Транспортного средства;
- ‘socket’ (необязательно): Экземпляр
socket.socket; -
- ‘asyncgen’ (необязательно): Асинхронный генератор, вызвавший
-
исключение.
Примечание
Этот метод не должен переопределяться в подклассах циклов событий. Для кастомизации обработки исключений используйте метод
set_exception_handler().
Включение отладочного режима
-
loop.get_debug() -
Получить отладочный режим (
bool) цикла событий.Значение по умолчанию —
True, если переменная окруженияPYTHONASYNCIODEBUGустановлена непустой строкой,Falseв противном случае.
-
loop.set_debug(enabled: bool) -
Установить отладочный режим цикла событий.
Изменено в версии 3.7: Теперь также можно использовать новый режим разработки Python для включения отладочного режима.
См. также
Отладочный режим asyncio.
Запуск дочерних процессов
Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном коде async/await рекомендуется использовать высокоуровневые функции asyncio.create_subprocess_shell() и asyncio.create_subprocess_exec() вместо них.
Примечание
В Windows цикл событий по умолчанию ProactorEventLoop поддерживает дочерние процессы, в то время как SelectorEventLoop — нет. Подробности см. в Поддержка дочерних процессов в Windows.
-
coroutine loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) -
Создаёт дочерний процесс из одной или нескольких строковых аргументов, указанных в args.
args должен быть списком строк, представленных:
-
str; - или
bytes, закодированных в кодировке файловой системы.
Первая строка указывает исполняемый файл программы, а остальные строки — аргументы. Вместе строковые аргументы образуют
argvпрограммы.Это аналогично классу
subprocess.Popenстандартной библиотеки, вызываемому сshell=Falseи списком строк, переданных в качестве первого аргумента; однако, в то время какPopenпринимает один аргумент, являющийся списком строк, subprocess_exec принимает несколько строковых аргументов.protocol_factory должно быть вызываемым объектом, возвращающим подкласс класса
asyncio.SubprocessProtocol.Другие параметры:
-
stdin может быть любым из перечисленных:
- объект, подобный файлу, представляющий канал, подключаемый к стандартному потоку ввода дочернего процесса с помощью
connect_write_pipe() - константа
subprocess.PIPE(по умолчанию), которая создаст новый канал и подключит его, - значение
None, которое заставит дочерний процесс унаследовать дескриптор файла из этого процесса - константа
subprocess.DEVNULL, которая указывает, что будет использован специальный файлos.devnull
- объект, подобный файлу, представляющий канал, подключаемый к стандартному потоку ввода дочернего процесса с помощью
-
stdout может быть любым из перечисленных:
- объект, подобный файлу, представляющий канал, подключаемый к стандартному потоку вывода дочернего процесса с помощью
connect_write_pipe() - константа
subprocess.PIPE(по умолчанию), которая создаст новый канал и подключит его, - значение
None, которое заставит дочерний процесс унаследовать дескриптор файла из этого процесса - константа
subprocess.DEVNULL, которая указывает, что будет использован специальный файлos.devnull
- объект, подобный файлу, представляющий канал, подключаемый к стандартному потоку вывода дочернего процесса с помощью
-
stderr может быть любым из перечисленных:
- объект, подобный файлу, представляющий канал, подключаемый к стандартному потоку ошибок дочернего процесса с помощью
connect_write_pipe() - константа
subprocess.PIPE(по умолчанию), которая создаст новый канал и подключит его, - значение
None, которое заставит дочерний процесс унаследовать дескриптор файла из этого процесса - константа
subprocess.DEVNULL, которая указывает, что будет использован специальный файлos.devnull - константа
subprocess.STDOUT, которая подключит поток ошибок к потоку вывода дочернего процесса
- объект, подобный файлу, представляющий канал, подключаемый к стандартному потоку ошибок дочернего процесса с помощью
-
Все остальные ключевые аргументы передаются в
subprocess.Popenбез интерпретации, за исключением bufsize, universal_newlines, shell, text, encoding и errors, которые не должны задаваться вовсе.API
asyncioдочерних процессов не поддерживает декодирование потоков как текста.bytes.decode()можно использовать для преобразования байтов, возвращаемых из потока, в текст.
См. конструктор класса
subprocess.Popenдля получения документации по другим аргументам.Возвращает пару
(transport, protocol), где transport соответствует базовому классуasyncio.SubprocessTransport, а protocol — это объект, созданный с помощью protocol_factory. -
-
coroutine loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) -
Создаёт дочерний процесс из cmd, которое может быть строкой
strилиbytes, закодированной в кодировке файловой системы, используя синтаксис «оболочки» платформы.Это аналогично классу
subprocess.Popenстандартной библиотеки, вызываемому сshell=True.protocol_factory должно быть вызываемым объектом, возвращающим подкласс класса
SubprocessProtocol.См.
subprocess_exec()для получения дополнительных сведений об остальных аргументах.Возвращает пару
(transport, protocol), где transport соответствует базовому классуSubprocessTransport, а protocol — это объект, созданный с помощью protocol_factory.
Примечание
Приложения должны гарантировать, что все пробелы и специальные символы должным образом заключены в кавычки, чтобы избежать уязвимостей впрыска команд. Функция shlex.quote() может использоваться для правильного экранирования пробелов и специальных символов в строках, которые будут использоваться для построения команд оболочки.
Обработчики обратных вызовов
-
class asyncio.Handle -
Объект-обёртку обратного вызова, возвращаемый
loop.call_soon()иloop.call_soon_threadsafe().-
cancel() -
Отмена обратного вызова. Если обратный вызов уже отменён или выполнен, этот метод не оказывает никакого влияния.
-
cancelled() -
Возвращает
True, если обратный вызов был отменён.Введено в версии 3.7.
-
-
class asyncio.TimerHandle -
Объект-обёртку обратного вызова, возвращаемый
loop.call_later()иloop.call_at().Этот класс является подклассом
Handle.-
when() -
Возвращает запланированное время обратного вызова в виде значения
floatсекунд.Время — абсолютная метка времени, использующая ту же временную отметку, что и
loop.time().Введено в версии 3.7.
-
Объекты сервера
Объекты сервера создаются функциями loop.create_server(), loop.create_unix_server(), start_server() и start_unix_server().
Не создавайте экземпляр класса напрямую.
-
class asyncio.Server -
Объекты Server являются асинхронными контекстными менеджерами. При использовании в операторе
async with, гарантируется, что объект Server закрыт и не принимает новые подключения, когда операторasync withзавершён:srv = await loop.create_server(...) async with srv: # some code # At this point, srv is closed and no longer accepts new connections.Изменено в версии 3.7: Объект Server является асинхронным контекстным менеджером начиная с Python 3.7.
-
close() -
Остановка обслуживания: закрытие сокетов прослушивания и установка атрибута
socketsвNone.Сокеты, представляющие существующие входящие подключения клиентов, остаются открытыми.
Сервер закрывается асинхронно, используйте сопрограмму
wait_closed()для ожидания закрытия сервера.
-
get_loop() -
Возвращает цикл событий, связанный с объектом сервера.
Введено в версии 3.7.
-
coroutine start_serving() -
Начать приём подключений.
Этот метод идемпотентен, поэтому его можно вызывать, когда сервер уже обслуживает подключения.
Ключевое слово-параметр start_serving в
loop.create_server()иasyncio.start_server()позволяет создать объект Server, который изначально не принимает подключения. В этом случаеServer.start_serving(), илиServer.serve_forever()можно использовать для начала приёма подключений сервером.Введено в версии 3.7.
-
coroutine serve_forever() -
Начать приём подключений до отмены сопрограммы. Отмена задачи
serve_foreverприводит к закрытию сервера.Этот метод может быть вызван, если сервер уже принимает подключения. Только одна задача
serve_foreverможет существовать на один объект Server.Пример:
async def client_connected(reader, writer): # Communicate with the client with # reader/writer streams. For example: await reader.readline() async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) await srv.serve_forever() asyncio.run(main('127.0.0.1', 0))Введено в версии 3.7.
-
is_serving() -
Возвращает
Trueесли сервер принимает новые подключения.Введено в версии 3.7.
-
coroutine wait_closed() -
Ожидание завершения метода
close().
-
sockets -
Список объектов
socket.socket, на которых сервер прослушивает подключения.Изменено в версии 3.7: До Python 3.7
Server.socketsвозвращал внутренний список сокетов сервера напрямую. В версии 3.7 возвращается копия этого списка.
-
Реализации цикла событий
asyncio поставляется с двумя различными реализациями цикла событий: SelectorEventLoop и ProactorEventLoop.
По умолчанию asyncio настраивается для использования SelectorEventLoop в Unix и ProactorEventLoop в Windows.
-
class asyncio.SelectorEventLoop -
Цикл событий, основанный на модуле
selectors.Использует наиболее эффективный селектор, доступный для данной платформы. Также возможно ручное определение точной реализации селектора для использования:
import asyncio import selectors class MyPolicy(asyncio.DefaultEventLoopPolicy): def new_event_loop(self): selector = selectors.SelectSelector() return asyncio.SelectorEventLoop(selector) asyncio.set_event_loop_policy(MyPolicy())Доступность: Unix, Windows.
-
class asyncio.ProactorEventLoop -
Цикл событий для Windows, который использует «Порты завершения I/O» (IOCP).
Доступность: Windows.
См. также
-
class asyncio.AbstractEventLoop -
Абстрактный базовый класс для совместимых с asyncio циклов событий.
Раздел Методы цикла событий перечисляет все методы, которые должна иметь любая альтернативная реализация
AbstractEventLoop.
Примеры
Обратите внимание, что все примеры в этом разделе намеренно показывают, как использовать низкоуровневые API цикла событий, такие как loop.run_forever() и loop.call_soon(). Современные приложения asyncio редко требуют написания кода таким способом; рассмотрите возможность использования высокоуровневых функций, таких как asyncio.run().
Привет мир с call_soon()
Пример использования метода loop.call_soon() для планирования обратного вызова. Обратный вызов отображает "Hello World", а затем останавливает цикл событий:
import asyncio
def hello_world(loop):
"""A callback to print 'Hello World' and stop the event loop"""
print('Hello World')
loop.stop()
loop = asyncio.get_event_loop()
# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример «Привет мир» с сопрограммой, созданный с помощью функции run().
Отображение текущей даты с call_later()
Пример обратного вызова, отображающего текущую дату каждую секунду. Обратный вызов использует метод loop.call_later() для перепланирования себя через 5 секунд, а затем останавливает цикл событий:
import asyncio
import datetime
def display_date(end_time, loop):
print(datetime.datetime.now())
if (loop.time() + 1.0) < end_time:
loop.call_later(1, display_date, end_time, loop)
else:
loop.stop()
loop = asyncio.get_event_loop()
# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример текущей даты с сопрограммой и функцией run().
Следить за дескриптором файла на события чтения
Ожидание, пока дескриптор файла получит данные, с помощью метода loop.add_reader(), а затем закрытие цикла событий:
import asyncio
from socket import socketpair
# Create a pair of connected file descriptors
rsock, wsock = socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# We are done: unregister the file descriptor
loop.remove_reader(rsock)
# Stop the event loop
loop.stop()
# Register the file descriptor for read event
loop.add_reader(rsock, reader)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
try:
# Run the event loop
loop.run_forever()
finally:
# We are done. Close sockets and the event loop.
rsock.close()
wsock.close()
loop.close()
См. также
- Аналогичный пример примера с использованием транспортов, протоколов и метода
loop.create_connection(). - Ещё один аналогичный пример примера с использованием высокоуровневой функции
asyncio.open_connection()и потоков.
Установить обработчики сигналов для SIGINT и SIGTERM
(Этот signals пример работает только в Unix.)
Регистрация обработчиков для сигналов SIGINT и SIGTERM с помощью метода loop.add_signal_handler():
import asyncio
import functools
import os
import signal
def ask_exit(signame, loop):
print("got signal %s: exit" % signame)
loop.stop()
async def main():
loop = asyncio.get_running_loop()
for signame in {'SIGINT', 'SIGTERM'}:
loop.add_signal_handler(
getattr(signal, signame),
functools.partial(ask_exit, signame, loop))
await asyncio.sleep(3600)
print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")
asyncio.run(main())
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/library/asyncio-eventloop.html