Цикл обработки событий
Исходный код: 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 и задач
- Открытие сетевых соединений
- Создание сетевых серверов
- Передача файлов
- Обновление TLS
- Наблюдение за дескрипторами файлов
- Работа с объектами сокетов напрямую
- DNS
- Работа с каналами
- Сигналы Unix
- Выполнение кода в пулах потоков или процессов
- API обработки ошибок
- Включение отладочного режима
- Запуск дочерних процессов
Запуск и остановка цикла
-
loop.run_until_complete(future) -
Запуск до завершения задачи (экземпляр
Future).Если аргумент является объектом корутины, он неявно планируется для выполнения как
asyncio.Task.Возвращает результат задачи или поднимает исключение.
-
loop.run_forever() -
Запуск цикла событий до вызова
stop().Если
stop()вызывается до вызоваrun_forever(), цикл опросит селектор ввода/вывода один раз с таймаутом 0, выполнит все обратные вызовы, запланированные в ответ на события ввода/вывода (и те, которые уже были запланированы), а затем завершится.Если
stop()вызывается во время выполненияrun_forever(), цикл выполнит текущую партию обратных вызовов и затем завершится. Обратите внимание, что новые обратные вызовы, запланированные обратными вызовами, в этом случае не будут выполнены; вместо этого они будут выполнены в следующий раз, когда будет вызванrun_forever()илиrun_until_complete().
-
loop.stop() -
Остановка цикла событий.
-
loop.is_running() -
Возвращает
True, если цикл событий в данный момент выполняется.
-
loop.is_closed() -
Возвращает
True, если цикл событий был закрыт.
-
loop.close() -
Закрытие цикла событий.
Цикл не должен выполняться, когда вызывается эта функция. Любые ожидающие обратные вызовы будут отброшены.
Этот метод очищает все очереди и завершает исполняемый модуль, но не ждет завершения работы исполняемого модуля.
Этот метод идемпотентен и необратим. Никаких других методов вызывать нельзя после закрытия цикла событий.
-
coroutine loop.shutdown_asyncgens() -
Планирует закрытие всех открытых объектов асинхронных генераторов с помощью вызова
aclose(). После вызова этого метода цикл событий выведет предупреждение, если новый асинхронный генератор будет итерироваться. Это необходимо для надежного завершения всех запланированных асинхронных генераторов.Обратите внимание, что вызов этой функции не нужен при использовании
asyncio.run().Пример:
try: loop.run_forever() finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()Введено в версии 3.6.
-
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, context=None) -
Планирует выполнение корутины 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 — объект корутины. Вызываемый объект должен возвращать объект, совместимый с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) -
Установить потоковое транспортное соединение с указанным адресом, заданным 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(по умолчанию). -
ssl_shutdown_timeout — время в секундах ожидания завершения закрытия SSL перед прерыванием соединения.
30.0секунд, еслиNone(по умолчанию).
Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop.Изменено в версии 3.6: Параметр socket.TCP_NODELAY по умолчанию устанавливается для всех TCP-соединений.
Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.
Изменено в версии 3.8: Добавлены параметры happy_eyeballs_delay и interleave.
Алгоритм Happy Eyeballs: Успех с хостами двойной стековой архитектуры. Когда путь и протокол IPv4 сервера работают, но путь и протокол IPv6 сервера не работают, приложение клиента двойной стековой архитектуры испытывает значительную задержку соединения по сравнению с клиентом только IPv4. Это нежелательно, так как заставляет клиент двойной стековой архитектуры иметь худший пользовательский опыт. В данном документе определяются требования к алгоритмам, которые уменьшают эту видимую пользователю задержку, и приводится алгоритм.
Для получения дополнительной информации: https://datatracker.ietf.org/doc/html/rfc6555
Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.
См. также
Функция
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 должно быть вызываемым объектом, возвращающим реализацию протокола.
В случае успеха возвращается кортеж
(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 и некоторых Unixes. Если константа socket.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 больше не поддерживается, так как использование socket.SO_REUSEADDR создаёт значительную проблему безопасности для UDP. Явное указание
reuse_address=Trueприведёт к исключению.В случае нескольких процессов с разными идентификаторами пользователей, присваивающих сокеты идентичному адресу UDP-сокета с
SO_REUSEADDR, входящие пакеты могут быть случайным образом распределены между сокетами.На поддерживаемых платформах можно использовать reuse_port как замену для подобной функциональности. С reuse_port используется socket.SO_REUSEPORT, который специально предотвращает присвоение сокетов тем же адресам сокета процессами с разными идентификаторами пользователей.
Изменено в версии 3.8: Добавлена поддержка Windows.
Изменено в версии 3.11: Параметр reuse_address, отключённый начиная с Python 3.9.0, 3.8.1, 3.7.6 и 3.6.10, был полностью удалён.
-
Если задан local_addr, это кортеж
-
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()для информации об аргументах этого метода.Доступность: Unix.
Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout. Параметр path теперь может быть объектом-путем.
Изменено в версии 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, ssl_handshake_timeout=None, ssl_shutdown_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(по умолчанию). -
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.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) -
Аналогично
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.Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.
-
coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None) -
Упаковывает уже принятое подключение в пару транспорт/протокол.
Этот метод может использоваться серверами, которые принимают подключения вне asyncio, но используют asyncio для их обработки.
Параметры:
- protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
-
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).Новое в версии 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.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, ssl_shutdown_timeout=None) -
Обновить существующее подключение на основе транспорта до TLS.
Создайте экземпляр кодера/декодера TLS и вставьте его между транспортом и протоколом. Кодер/декодер реализует как протокол для транспорта, так и транспорт для протокола.
Возвращает созданный экземпляр с двумя интерфейсами. После await, протокол должен перестать использовать исходный транспорт и общаться только с возвращённым объектом, так как кодер кэширует данные со стороны протокола и периодически обменивается дополнительными пакетами сессии TLS с транспортом.
В некоторых ситуациях (например, когда передаваемый транспорт уже закрывается) это может вернуть
None.Параметры:
-
экземпляры транспорта и протокола, которые возвращают методы, такие как
create_server()иcreate_connection(). -
sslcontext: настроенный экземпляр
SSLContext. -
передайте
Trueпри обновлении подключения на стороне сервера (как при создании с помощьюcreate_server()). - server_hostname: устанавливает или переопределяет имя хоста, по которому будет проверяться сертификат целевого сервера.
-
ssl_handshake_timeout — (для подключения TLS) время в секундах ожидания завершения рукопожатия TLS перед прерыванием подключения.
60.0секунд, еслиNone(по умолчанию). -
ssl_shutdown_timeout — время в секундах ожидания завершения закрытия SSL перед прерыванием подключения.
30.0секунд, еслиNone(по умолчанию).
Добавлена в версии 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()для передачи именованных аргументов в 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().Возвращает принятые данные в виде объекта bytes.
sock должен быть неблокирующим сокетом.
Изменено в версии 3.7: Хотя этот метод всегда документировался как метод корутины, в версиях до Python 3.7 он возвращал
Future. Начиная с Python 3.7 это методasync def.
-
coroutine loop.sock_recv_into(sock, buf) -
Приём данных из sock в буфер buf. Моделируется по блокирующему методу
socket.recv_into().Возвращает количество байт, записанных в буфер.
sock должен быть неблокирующим сокетом.
Введено в версии 3.7.
-
coroutine loop.sock_recvfrom(sock, bufsize) -
Приём дейтаграммы размером до bufsize из sock. Асинхронный аналог
socket.recvfrom().Возвращает кортеж (принятые данные, удалённый адрес).
sock должен быть неблокирующим сокетом.
Введено в версии 3.11.
-
coroutine loop.sock_recvfrom_into(sock, buf, nbytes=0) -
Приём дейтаграммы размером до nbytes из sock в buf. Асинхронный аналог
socket.recvfrom_into().Возвращает кортеж (количество принятых байт, удалённый адрес).
sock должен быть неблокирующим сокетом.
Введено в версии 3.11.
-
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_sendto(sock, data, address) -
Отправка дейтаграммы с sock на address. Асинхронный аналог
socket.sendto().Возвращает количество отправленных байт.
sock должен быть неблокирующим сокетом.
Введено в версии 3.11.
-
coroutine loop.sock_connect(sock, address) -
Подключение sock к удалённому сокету по адресу address.
Асинхронный аналог
socket.connect().sock должен быть неблокирующим сокетом.
Изменено в версии 3.5.2:
addressбольше не нуждается в разрешении.sock_connectбудет пытаться проверить, уже ли разрешен address, вызвавsocket.inet_pton(). Если нет, будет использованloop.getaddrinfo()для разрешения address.См. также
-
coroutine loop.sock_accept(sock) -
Принятие подключения. Моделируется по блокирующему методу
socket.accept().Сокет должен быть привязан к адресу и прослушивать подключения. Результатом является пара
(conn, address), где conn — новый объект сокета, который можно использовать для отправки и получения данных по соединению, а 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.11: executor должен быть экземпляром
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 для включения отладочного режима.
-
loop.slow_callback_duration -
Этот атрибут можно использовать для установки минимального времени выполнения в секундах, которое считается «медленным». При включенном отладочном режиме «медленные» обратные вызовы регистрируются.
Значение по умолчанию — 100 миллисекунд.
См. также
Режим отладки 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.
Примечание
Приложения несут ответственность за обеспечение того, чтобы все пробелы и специальные символы были должным образом процитированы, чтобы избежать уязвимостей shell injection. Функция 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().
Не следует создавать экземпляры класса 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: Этот класс был публично доступен как
asyncio.Serverв Python 3.9.11, 3.10.3 и 3.11.-
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 -
Список объектов, похожих на сокеты,
asyncio.trsock.TransportSocket, на которых сервер прослушивает подключения.Изменено в версии 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, использующий «Порты завершения ввода-вывода» (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.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()
См. также
Аналогичный пример «Привет, мир» с использованием корутины и функции 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()
См. также
Аналогичный пример отображения текущей даты с использованием корутины и функции 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()
См. также
- Аналогичный пример примера с использованием транспортов, протоколов и метода
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.11/library/asyncio-eventloop.html