Цикл событий
Исходный код: Lib/asyncio/events.py, Lib/asyncio/base_events.py
Предисловие
Цикл событий является ядром каждого приложения asyncio. Циклы событий выполняют асинхронные задачи и обратные вызовы, выполняют операции ввода-вывода сети и запускают подпроцессы.
Разработчики приложений обычно должны использовать высокоуровневые функции asyncio, такие как asyncio.run(), и им редко потребуется обращаться к объекту цикла или вызывать его методы. Этот раздел предназначен в основном для авторов кода, библиотек и фреймворков более низкого уровня, которым требуется более тонкий контроль над поведением цикла событий.
Получение цикла событий
Следующие функции низкого уровня могут использоваться для получения, установки или создания цикла событий:
-
asyncio.get_running_loop() -
Возвращает работающий цикл событий в текущей потоке ОС.
Если цикла событий нет, выбрасывается
RuntimeError. Эта функция может вызываться только из корутины или обратного вызова.Новая в версии 3.7.
-
asyncio.get_event_loop() -
Получить текущий цикл событий.
Если в текущей потоке ОС нет текущего цикла событий, поток ОС является главным, а
set_event_loop()еще не был вызван, asyncio создаст новый цикл событий и установит его как текущий.Поскольку у этой функции довольно сложное поведение (особенно при использовании пользовательских политик цикла событий), использование функции
get_running_loop()предпочтительнееget_event_loop()в корутинах и обратных вызовах.Также рассмотрите возможность использования функции
asyncio.run()вместо ручного создания и закрытия цикла событий.
-
asyncio.set_event_loop(loop) -
Установить loop как текущий цикл событий для текущей потока ОС.
-
asyncio.new_event_loop() -
Создать и вернуть новый объект цикла событий.
Обратите внимание, что поведение функций get_event_loop(), set_event_loop() и new_event_loop() может быть изменено с помощью установки пользовательской политики цикла событий.
Содержание
Эта страница документации содержит следующие разделы:
- Раздел Методы цикла событий — это справочная документация API цикла событий;
- В разделе Обработки обратных вызовов описываются экземпляры
HandleиTimerHandle, которые возвращаются из методов планирования, таких какloop.call_soon()иloop.call_later(); - Раздел Объекты сервера документирует типы, возвращаемые из методов цикла событий, таких как
loop.create_server(); - В разделе Реализации циклов событий описываются классы
SelectorEventLoopиProactorEventLoop; - В разделе Примеры показано, как работать с некоторыми API цикла событий.
Методы цикла событий
Циклы событий предоставляют низкоуровневые API для следующих задач:
- Запуск и остановка цикла
- Планирование обратных вызовов
- Планирование отложенных обратных вызовов
- Создание объектов Future и Task
- Открытие сетевых подключений
- Создание сетевых серверов
- Передача файлов
- Обновление TLS
- Мониторинг дескрипторов файлов
- Работа с объектами сокетов напрямую
- DNS
- Работа с каналами
- Сигналы Unix
- Выполнение кода в пулах потоков или процессов
- API обработки ошибок
- Включение отладочного режима
- Запуск дочерних процессов
Запуск и остановка цикла
-
loop.run_until_complete(future) -
Запуск до завершения future (экземпляра
Future).Если аргумент является объектом корутины, он неявно планируется для выполнения как
asyncio.Task.Возвращает результат Future или поднимает его исключение.
-
loop.run_forever() -
Запуск цикла событий до вызова
stop().Если
stop()вызывается до вызоваrun_forever(), цикл один раз проверит селектор ввода-вывода с таймаутом 0, выполнит все обратные вызовы, запланированные в ответ на события ввода-вывода (и те, что уже были запланированы), а затем завершится.Если
stop()вызывается во время работыrun_forever(), цикл выполнит текущую партию обратных вызовов и затем завершится. Обратите внимание, что новые обратные вызовы, запланированные обратными вызовами, в этом случае не будут выполнены; вместо этого они будут выполнены в следующий раз, когда вызываетсяrun_forever()илиrun_until_complete().
-
loop.stop() -
Останавливает цикл событий.
-
loop.is_running() -
Возвращает
True, если цикл событий в данный момент работает.
-
loop.is_closed() -
Возвращает
True, если цикл событий был закрыт.
-
loop.close() -
Закрывает цикл событий.
Цикл не должен быть запущен при вызове этой функции. Все ожидающие обратные вызовы будут отброшены.
Этот метод очищает все очереди и останавливает исполняемый процесс, но не ожидает завершения исполняемого процесса.
Этот метод идемпотентен и необратим. После закрытия цикла событий другие методы вызывать не следует.
-
coroutine loop.shutdown_asyncgens() -
Планирует закрытие всех открытых в данный момент объектов асинхронного генератора с помощью вызова
aclose(). После вызова этого метода цикл событий выведет предупреждение, если новый асинхронный генератор будет перебираться. Это необходимо для надежной финализации всех запланированных асинхронных генераторов.Обратите внимание, что при использовании
asyncio.run()вызывать эту функцию не нужно.Пример:
try: loop.run_forever() finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()Введено в версии 3.6.
-
coroutine loop.shutdown_default_executor() -
Планирует закрытие исполняемого процесса по умолчанию и ожидает, пока он не присоединит все потоки в
ThreadPoolExecutor. После вызова этого метода вызовRuntimeError, еслиloop.run_in_executor()вызывается с использованием исполняемого процесса по умолчанию.Обратите внимание, что при использовании
asyncio.run()вызывать эту функцию не нужно.Введено в версии 3.9.
Планирование обратных вызовов
-
loop.call_soon(callback, *args, context=None) -
Планирует обратный вызов callback с аргументами args на следующей итерации цикла событий.
Обратные вызовы вызываются в том порядке, в котором они зарегистрированы. Каждый обратный вызов будет вызван ровно один раз.
Необязательный ключевой аргумент context позволяет указать пользовательский
contextvars.Contextдля выполнения callback. При отсутствии context используется текущий контекст.Возвращается экземпляр
asyncio.Handle, который можно использовать для отмены обратного вызова.Этот метод не потокобезопасен.
-
loop.call_soon_threadsafe(callback, *args, context=None) -
Потокобезопасная версия
call_soon(). Должна использоваться для планирования обратных вызовов из другого потока.Вызывает исключение
RuntimeError, если вызывается для цикла, который закрыт. Это может произойти во вторичном потоке, когда основное приложение закрывается.См. раздел конкурентности и многопоточности документации.
Изменено в версии 3.7: Добавлен ключевой параметр context. Подробнее см. PEP 567.
Примечание
Большинство функций планирования asyncio не позволяют передавать ключевые аргументы. Для этого используйте functools.partial():
# will schedule "print("Hello", flush=True)"
loop.call_soon(
functools.partial(print, "Hello", flush=True))
Использование объектов partial обычно удобнее, чем использование лямбда-функций, так как asyncio может лучше отображать объекты partial в отладочных и ошибочных сообщениях.
Планирование отложенных обратных вызовов
Цикл событий предоставляет механизмы для планирования обратных вызовов функций для их вызова в определенный момент будущего. Цикл событий использует монотонные часы для отслеживания времени.
-
loop.call_later(delay, callback, *args, context=None) -
Запланировать вызов callback через указанное количество delay секунд (может быть целым или дробным числом).
Возвращается экземпляр
asyncio.TimerHandle, который можно использовать для отмены обратного вызова.callback будет вызван ровно один раз. Если два обратных вызова запланированы на одно и то же время, порядок их вызова не определен.
Дополнительные позиционные аргументы args будут переданы обратному вызову при его вызове. Если вы хотите, чтобы обратный вызов был вызван с именованными аргументами, используйте
functools.partial().Необязательный ключевой аргумент context позволяет указать пользовательский
contextvars.Contextдля выполнения callback. При отсутствии context используется текущий контекст.Изменено в версии 3.7: Добавлен ключевой аргумент context. Подробнее см. PEP 567.
Изменено в версии 3.8: В Python 3.7 и ранее с реализацией цикла событий по умолчанию delay не мог превышать одного дня. Эта проблема исправлена в Python 3.8.
-
loop.call_at(when, callback, *args, context=None) -
Запланировать вызов callback в заданный абсолютный момент времени when (целое или дробное число), используя ту же временную метку, что и
loop.time().Поведение этого метода такое же, как у
call_later().Возвращается экземпляр
asyncio.TimerHandle, который можно использовать для отмены обратного вызова.Изменено в версии 3.7: Добавлен ключевой аргумент context. Подробнее см. PEP 567.
Изменено в версии 3.8: В Python 3.7 и ранее разница между when и текущим временем не могла превышать одного дня. Эта проблема исправлена в Python 3.8.
-
loop.time() -
Возвращает текущее время в виде значения
floatсогласно внутренним монотонным часам цикла событий.
Примечание
Изменено в версии 3.8: В Python 3.7 и ранее таймауты (относительный delay или абсолютный when) не должны превышать одного дня. Эта проблема исправлена в Python 3.8.
См. также
Функцию asyncio.sleep().
Создание объектов Future и задач
-
loop.create_future() -
Создаёт объект
asyncio.Future, привязанный к циклу событий.Это предпочтительный способ создания объектов Future в asyncio. Это позволяет сторонним циклам событий предоставлять альтернативные реализации объекта Future (с лучшей производительностью или инструментарием).
Добавлена в версии 3.5.2.
-
loop.create_task(coro, *, name=None) -
Планирует выполнение корутин. Возвращает объект
Task.Сторонние циклы событий могут использовать свои собственные подклассы
Taskдля межпрограммной совместимости. В этом случае тип результата является подклассомTask.Если аргумент name предоставлен и не
None, он устанавливается в качестве имени задачи с помощьюTask.set_name().Изменено в версии 3.8: Добавлен параметр
name.
-
loop.set_task_factory(factory) -
Устанавливает фабрику задач, которая будет использоваться
loop.create_task().Если factory
Noneбудет установлена фабрика задач по умолчанию. В противном случае factory должен быть вызываемым с сигнатурой, соответствующей(loop, coro), где loop — ссылка на активный цикл событий, а coro — объект корутины. Вызываемый объект должен возвращать объект, совместимый сasyncio.Future.
-
loop.get_task_factory() -
Возвращает фабрику задач или
Noneесли используется фабрика по умолчанию.
Открытие сетевых подключений
-
coroutine loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None) -
Установить поток связи с заданным адресом, указанным в host и port.
Семейство сокетов может быть либо
AF_INET, либоAF_INET6в зависимости от host (или аргумента family, если он предоставлен).Тип сокета будет
SOCK_STREAM.protocol_factory должно быть вызываемым объектом, возвращающим реализацию протокола asyncio.
Этот метод попытается установить соединение в фоновом режиме. При успехе он возвращает
(transport, protocol)пару.Хронологический обзор базовой операции:
- Соединение устанавливается, и для него создаётся транспорт.
- protocol_factory вызывается без аргументов и ожидается, что вернёт экземпляр протокола.
- Экземпляр протокола связывается с транспортом, вызывая его метод
connection_made(). - В случае успеха возвращается
(transport, protocol)кортеж.
Созданный транспорт представляет собой двунаправленный поток, реализация которого зависит от конкретной реализации.
Другие аргументы:
-
ssl: если указан и не равен 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 не должны быть указаны. -
local_addr, если указан, представляет собой
(local_host, local_port)кортеж, используемый для привязки сокета локально. local_host и local_port находятся с помощьюgetaddrinfo(), аналогично host и port. -
ssl_handshake_timeout представляет собой (для TLS-соединения) время в секундах ожидания завершения рукопожатия TLS перед прерыванием соединения.
60.0секунд, еслиNone(по умолчанию).
Добавлено в версии 3.8: Добавлены параметры happy_eyeballs_delay и interleave.
Алгоритм Happy Eyeballs: Успех с хостами с двойной адресацией. Когда путь и протокол IPv4 сервера работают, но путь и протокол IPv6 сервера не работают, клиентское приложение с двойной адресацией испытывает значительную задержку соединения по сравнению с IPv4-только клиентом. Это нежелательно, поскольку это приводит к тому, что у клиента с двойной адресацией ухудшается пользовательский опыт. В данном документе определяются требования к алгоритмам, которые уменьшают эту видимую для пользователя задержку, и предлагается алгоритм.
Для получения дополнительной информации: https://tools.ietf.org/html/rfc6555
Добавлено в версии 3.7: Параметр ssl_handshake_timeout.
Изменено в версии 3.6: Опция сокета
TCP_NODELAYустанавливается по умолчанию для всех TCP-соединений.Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop.См. также
Функция
open_connection()— это альтернативный API высокого уровня. Она возвращает пару (StreamReader,StreamWriter), которые можно использовать непосредственно в коде async/await.
-
coroutine loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None) -
Примечание
Параметр reuse_address больше не поддерживается, так как использование
SO_REUSEADDRпредставляет собой значительную угрозу безопасности для UDP. Явное указаниеreuse_address=Trueвызовет исключение.Когда несколько процессов с разными идентификаторами пользователей присваивают сокеты одинаковому адресу UDP-соккета с
SO_REUSEADDR, входящие пакеты могут случайным образом распределяться между сокетами.Для поддерживаемых платформ reuse_port можно использовать как замену для аналогичной функциональности. С reuse_port используется
SO_REUSEPORT, что специально предотвращает присвоение сокетов процессами с разными идентификаторами пользователей одному адресу сокета.Создать соединение дейтаграммы.
Семейство сокетов может быть
AF_INET,AF_INET6илиAF_UNIX, в зависимости от host (или аргумента family, если он предоставлен).Тип сокета будет
SOCK_DGRAM.protocol_factory должно быть вызываемым объектом, возвращающим реализацию протокола.
В случае успеха возвращается кортеж
(transport, protocol).Другие аргументы:
-
local_addr, если указан, представляет собой кортеж
(local_host, local_port), используемый для привязки сокета локально. local_host и local_port ищутся с помощьюgetaddrinfo(). -
remote_addr, если указан, представляет собой кортеж
(remote_host, remote_port), используемый для подключения сокета к удаленному адресу. remote_host и remote_port ищутся с помощьюgetaddrinfo(). -
family, proto, flags — это необязательные семейство адресов, протокол и флаги, которые должны быть переданы в
getaddrinfo()для разрешения host. Если указаны, они должны быть целыми числами из соответствующих констант модуляsocket. -
reuse_port сообщает ядру, что этот конечный пункт может быть привязан к тому же порту, что и другие существующие привязанные конечные пункты, при условии, что все они устанавливают этот флаг при создании. Этот параметр не поддерживается в Windows и некоторых Unix-системах. Если константа
SO_REUSEPORTне определена, эта возможность не поддерживается. - allow_broadcast сообщает ядру, что этот конечный пункт может отправлять сообщения на адрес широковещательной передачи.
-
sock можно необязательно указать для использования существующего, уже подключенного объекта
socket.socket, который будет использоваться транспортным средством. Если указан, local_addr и remote_addr должны быть опущены (должны бытьNone).
См. примеры протокола клиента эхо-сервера UDP и протокола сервера эхо-сервера UDP.
Изменено в версии 3.4.4: Были добавлены параметры family, proto, flags, reuse_address, reuse_port, allow_broadcast и sock.
Изменено в версии 3.8.1: Параметр reuse_address больше не поддерживается из-за проблем безопасности.
Изменено в версии 3.8: Добавлена поддержка Windows.
-
local_addr, если указан, представляет собой кортеж
-
coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None) -
Создать Unix-соединение.
Семейство сокетов будет
AF_UNIX; тип сокета будетSOCK_STREAM.В случае успеха возвращается кортеж
(transport, protocol).path — это имя сокета Unix-домена и является обязательным, если не указан параметр sock. Поддерживаются абстрактные Unix-сокеты, пути
str,bytesиPath.См. документацию метода
loop.create_connection()для получения информации об аргументах этого метода.Доступность: Unix.
Добавлена в версии 3.7: Параметр ssl_handshake_timeout.
Изменено в версии 3.7: Теперь параметр path может быть объектом, подобным пути.
Создание сетевых серверов
-
coroutine loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True) -
Создает TCP-сервер (тип сокета
SOCK_STREAM), прослушивающий порт port на адресе host.Возвращает объект
Server.Аргументы:
- protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
-
Параметр host может принимать несколько типов, определяющих, где сервер будет прослушивать:
- Если host является строкой, TCP-сервер привязывается к одному сетевому интерфейсу, указанному в host.
- Если host является последовательностью строк, TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в последовательности.
- Если host является пустой строкой или
None, предполагаются все интерфейсы, и будет возвращён список нескольких сокетов (вероятно, один для IPv4 и другой для IPv6).
- Параметр port может быть установлен для указания порта, на котором сервер должен прослушивать. Если
0илиNone(по умолчанию), будет выбран случайный свободный порт (обратите внимание, что если host указывает на несколько сетевых интерфейсов, для каждого интерфейса будет выбран другой случайный порт). -
family может быть установлен в
socket.AF_INETилиAF_INET6для принудительного использования IPv4 или IPv6. Если не указано, family определяется по имени хоста (по умолчаниюAF_UNSPEC). -
flags — битовая маска для
getaddrinfo(). - sock может быть указан для использования существующего объекта сокета. Если указано, host и port не должны быть указаны.
-
backlog — максимальное количество ожидающих соединений, передаваемое в
listen()(по умолчанию 100). -
ssl может быть установлен в экземпляр
SSLContextдля включения TLS для принятых соединений. -
reuse_address сообщает ядру использовать локальный сокет в состоянии
TIME_WAIT, не дожидаясь его естественного таймаута. Если не указано, автоматически устанавливается вTrueна Unix. - reuse_port сообщает ядру разрешить этому конечной точке привязку к тому же порту, что и другим существующим конечным точкам, если все они установили этот флаг при создании. Этот параметр не поддерживается в Windows.
-
ssl_handshake_timeout (для TLS-сервера) — время в секундах ожидания завершения TLS-рукопожатия до прерывания соединения.
60.0секунд, еслиNone(по умолчанию). -
start_serving, установленный в
True(по умолчанию), заставляет созданный сервер немедленно начать принимать подключения. При значенииFalse, пользователь должен ожидатьServer.start_serving()илиServer.serve_forever()для начала приёма подключений.
Новое в версии 3.7: Добавлены параметры ssl_handshake_timeout и start_serving.
Изменено в версии 3.6: Параметр сокета
TCP_NODELAYпо умолчанию установлен для всех TCP-соединений.Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop.Изменено в версии 3.5.1: Параметр host может быть последовательностью строк.
См. также
Функция
start_server()— это API более высокого уровня, который возвращает паруStreamReaderиStreamWriter, которые могут быть использованы в асинхронном коде.
-
coroutine loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True) -
Аналогично
loop.create_server(), но работает с семейством сокетовAF_UNIX.path — имя сокета Unix-домена и требуется, если не указан аргумент sock. Поддерживаются пути для абстрактных Unix-сокетов,
str,bytesиPath.См. документацию метода
loop.create_server()для получения информации об аргументах этого метода.Доступность: Unix.
Новое в версии 3.7: Параметры ssl_handshake_timeout и start_serving.
Изменено в версии 3.7: Параметр path теперь может быть объектом
Path.
-
coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None) -
Оборачивает уже принятое соединение в пару транспорт/протокол.
Этот метод может использоваться серверами, которые принимают подключения вне asyncio, но используют asyncio для их обработки.
Параметры:
- protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
-
sock — существующий объект сокета, возвращённый из
socket.accept. -
ssl может быть установлен в
SSLContextдля включения SSL для принятых соединений. -
ssl_handshake_timeout (для SSL-соединения) — время в секундах ожидания завершения SSL-рукопожатия до прерывания соединения.
60.0секунд, еслиNone(по умолчанию).
Возвращает пару
(transport, protocol).Новое в версии 3.7: Параметр ssl_handshake_timeout.
Новое в версии 3.5.3.
Передача файлов
-
coroutine loop.sendfile(transport, file, offset=0, count=None, *, fallback=True) -
Передает file по transport. Возвращает общее количество переданных байтов.
Метод использует высокопроизводительный
os.sendfile(), если доступен.file должен быть объектом файла, открытым в двоичном режиме.
offset указывает, с какой позиции начать чтение файла. Если указано, count — это общее количество байтов для передачи, а не передача файла до достижения EOF. Положение файла всегда обновляется, даже при возникновении ошибки в этом методе, и можно использовать
file.tell()для получения фактического количества переданных байтов.fallback, установленное в
True, заставляет asyncio вручную читать и отправлять файл, когда платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет на Unix).Возникает
SendfileNotAvailableError, если система не поддерживает системный вызов sendfile и fallback равноFalse.Новое в версии 3.7.
Обновление TLS
-
coroutine loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None) -
Обновить существующее транспортное соединение до TLS.
Возвращает новую экземпляр транспорта, которую протокол должен немедленно начать использовать после await. Экземпляр transport, переданный в метод start_tls, больше никогда не должен использоваться.
Параметры:
-
экземпляры transport и protocol, которые возвращают методы, такие как
create_server()иcreate_connection(). -
sslcontext: настроенный экземпляр
SSLContext. -
server_side передайте
Trueпри обновлении серверного соединения (например, созданного методомcreate_server()). - server_hostname: устанавливает или переопределяет имя хоста, по которому будет проверяться сертификат целевого сервера.
-
ssl_handshake_timeout — (для TLS-соединения) время в секундах ожидания завершения рукопожатия TLS перед прерыванием соединения.
60.0секунд, еслиNone(по умолчанию).
Введено в версии 3.7.
-
экземпляры transport и protocol, которые возвращают методы, такие как
Отслеживание дескрипторов файлов
-
loop.add_reader(fd, callback, *args) -
Начать мониторинг дескриптора файла fd на доступность для чтения и вызвать callback со значениями аргументов, как только fd станет доступен для чтения.
-
loop.remove_reader(fd) -
Остановить мониторинг дескриптора файла fd на доступность для чтения.
-
loop.add_writer(fd, callback, *args) -
Начать мониторинг дескриптора файла fd на доступность для записи и вызвать callback со значениями аргументов, как только fd станет доступен для записи.
Используйте
functools.partial()для передачи аргументов ключевого слова в callback.
-
loop.remove_writer(fd) -
Остановить мониторинг дескриптора файла fd на доступность для записи.
См. также раздел Поддержка платформ для некоторых ограничений этих методов.
Работа с объектами сокетов напрямую
В целом, реализации протоколов, использующие API на основе транспорта, такие как loop.create_connection() и loop.create_server(), работают быстрее, чем реализации, работающие напрямую с сокетами. Однако есть некоторые случаи, когда производительность не является критической, и работа с объектами socket напрямую более удобна.
-
coroutine loop.sock_recv(sock, nbytes) -
Принять до nbytes байт из sock. Асинхронная версия
socket.recv().Возвращает полученные данные в виде объекта bytes.
sock должен быть сокетом в режиме без ожидания.
Изменено в версии 3.7: Несмотря на то, что этот метод всегда документировался как метод корутины, до Python 3.7 он возвращал
Future. С Python 3.7 этоasync defметод.
-
coroutine loop.sock_recv_into(sock, buf) -
Получить данные из sock в буфер buf. Моделируется по аналогии с блокирующим методом
socket.recv_into().Возвращает количество байт, записанных в буфер.
sock должен быть сокетом в режиме без ожидания.
Введено в версии 3.7.
-
coroutine loop.sock_sendall(sock, data) -
Отправить data в сокет sock. Асинхронная версия
socket.sendall().Этот метод продолжает отправлять данные в сокет, пока все данные в data не будут отправлены или не произойдёт ошибка.
Noneвозвращается при успешном завершении. В случае ошибки генерируется исключение. Кроме того, нет способа определить, сколько данных, если таковые имеются, было успешно обработано получающей стороной соединения.sock должен быть сокетом в режиме без ожидания.
Изменено в версии 3.7: Хотя метод всегда документировался как метод корутины, до Python 3.7 он возвращал
Future. С Python 3.7 этоasync defметод.
-
coroutine loop.sock_connect(sock, address) -
Подключить sock к удалённому сокету по адресу address.
Асинхронная версия
socket.connect().sock должен быть сокетом в режиме без ожидания.
Изменено в версии 3.5.2:
addressбольше не нуждается в разрешении.sock_connectпопытается проверить, уже ли разрешён адрес, вызвавsocket.inet_pton(). Если нет, будет использоватьсяloop.getaddrinfo()для разрешения адреса.См. также
-
coroutine loop.sock_accept(sock) -
Принять соединение. Моделируется по аналогии с блокирующим методом
socket.accept().Сокет должен быть связан с адресом и ожидать соединений. Возвращаемое значение — пара
(conn, address), где conn — новый объект сокета, пригодный для отправки и получения данных по соединению, а address — адрес, привязанный к сокету на другом конце соединения.sock должен быть сокетом в режиме без ожидания.
Изменено в версии 3.7: Хотя метод всегда документировался как метод корутины, до Python 3.7 он возвращал
Future. С Python 3.7 этоasync defметод.См. также
-
coroutine loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True) -
Отправить файл, используя высокопроизводительный
os.sendfile, если это возможно. Возвращает общее количество отправленных байт.Асинхронная версия
socket.sendfile().sock должен быть сокетом в режиме без ожидания типа
socket.SOCK_STREAMsocket.file должен быть регулярным объектом файла, открытым в двоичном режиме.
offset указывает, с какого места начать чтение файла. Если указан, count — общее количество байт для передачи, в отличие от отправки файла до достижения 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) asyncio.run(main())Этот метод возвращает объект
asyncio.Future.Используйте
functools.partial()для передачи аргументов ключевых слов в func.Изменено в версии 3.5.3:
loop.run_in_executor()больше не настраиваетmax_workersисполнителя пула потоков, который он создает, вместо этого оставляя это исполнителю пула потоков (ThreadPoolExecutor) для установки значения по умолчанию.
-
loop.set_default_executor(executor) -
Установить executor в качестве исполнителя по умолчанию, используемого методом
run_in_executor(). executor должен быть экземпляромThreadPoolExecutor.Устарело начиная с версии 3.8: Использование исполнителя, который не является экземпляром
ThreadPoolExecutor, устарело и вызовет ошибку в Python 3.9.executor должен быть экземпляром
concurrent.futures.ThreadPoolExecutor.
Обработка ошибок API
Позволяет настраивать обработку исключений в цикле событий.
-
loop.set_exception_handler(handler) -
Установить handler в качестве нового обработчика исключений цикла событий.
Если handler равен
None, будет установлен обработчик исключений по умолчанию. В противном случае, handler должен быть вызываемым объектом с сигнатурой, соответствующей(loop, context), гдеloop— ссылка на активный цикл событий, аcontext— объектdict, содержащий детали исключения (см. документациюcall_exception_handler()для получения подробностей о контексте).
-
loop.get_exception_handler() -
Возвращает текущий обработчик исключений или
None, если пользовательский обработчик исключений не был установлен.Введено в версии 3.5.2.
-
loop.default_exception_handler(context) -
Обработчик исключений по умолчанию.
Вызывается при возникновении исключения и отсутствии установленного обработчика исключений. Он может вызываться пользовательским обработчиком исключений для делегирования поведения обработчику по умолчанию.
Параметр context имеет то же значение, что и в
call_exception_handler().
-
loop.call_exception_handler(context) -
Вызывает текущий обработчик исключений цикла событий.
context — это объект
dict, содержащий следующие ключи (в будущих версиях Python могут быть добавлены новые ключи):- ‘message’: Сообщение об ошибке;
- ‘exception’ (необязательно): Объект исключения;
- ‘future’ (необязательно): экземпляр
asyncio.Future; - ‘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()можно использовать для того, чтобы Server начал принимать подключения.Введено в версии 3.7.
-
coroutine serve_forever() -
Начать прием подключений до отмены корутины. Отмена задачи
serve_foreverприводит к закрытию сервера.Этот метод может быть вызван, если сервер уже принимает подключения. Только одна задача
serve_foreverможет существовать для одного объекта Server.Пример:
async def client_connected(reader, writer): # Communicate with the client with # reader/writer streams. For example: await reader.readline() async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) await srv.serve_forever() asyncio.run(main('127.0.0.1', 0))Введено в версии 3.7.
-
is_serving() -
Возвращает
True, если сервер принимает новые подключения.Введено в версии 3.7.
-
coroutine wait_closed() -
Ожидать завершения метода
close().
-
sockets -
Список объектов
socket.socket, на которых сервер прослушивает подключения.Изменено в версии 3.7: До Python 3.7
Server.socketsвозвращал внутренний список сокетов сервера напрямую. В 3.7 возвращается копия этого списка.
-
Реализации цикла событий
В asyncio есть две различные реализации цикла событий: SelectorEventLoop и ProactorEventLoop.
По умолчанию asyncio настроен на использование SelectorEventLoop в Unix и ProactorEventLoop в Windows.
-
class asyncio.SelectorEventLoop -
Цикл событий, основанный на модуле
selectors.Использует наиболее эффективный селектор, доступный для данной платформы. Также можно вручную настроить точную реализацию селектора, которую необходимо использовать:
import asyncio import selectors selector = selectors.SelectSelector() loop = asyncio.SelectorEventLoop(selector) asyncio.set_event_loop(loop)
Доступность: Unix, Windows.
-
class asyncio.ProactorEventLoop -
Цикл событий для Windows, который использует «I/O Completion Ports» (IOCP).
Доступность: Windows.
См. также
-
class asyncio.AbstractEventLoop -
Абстрактный базовый класс для циклов событий, совместимых с asyncio.
В разделе Методы цикла событий перечислены все методы, которые должна определить альтернативная реализация
AbstractEventLoop.
Примеры
Обратите внимание, что все примеры в этом разделе намеренно демонстрируют использование низкоуровневых API цикла событий, таких как loop.run_forever() и loop.call_soon(). Современные приложения asyncio редко требуют написания кода таким образом; рассмотрите использование высокоуровневых функций, таких как asyncio.run().
Привет мир с call_soon()
Пример использования метода loop.call_soon() для планирования обратного вызова. Обратный вызов отображает "Hello World" и затем останавливает цикл событий:
import asyncio
def hello_world(loop):
"""A callback to print 'Hello World' and stop the event loop"""
print('Hello World')
loop.stop()
loop = asyncio.get_event_loop()
# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример «Привет мир» с использованием корутины и функции run().
Отображение текущей даты с помощью call_later()
Пример обратного вызова, отображающего текущую дату каждую секунду. Обратный вызов использует метод loop.call_later() для повторного планирования через 5 секунд, а затем останавливает цикл событий:
import asyncio
import datetime
def display_date(end_time, loop):
print(datetime.datetime.now())
if (loop.time() + 1.0) < end_time:
loop.call_later(1, display_date, end_time, loop)
else:
loop.stop()
loop = asyncio.get_event_loop()
# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
# Blocking call interrupted by loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример текущей даты с использованием корутины и функции run().
Отслеживание дескриптора файла на события чтения
Ожидание, пока дескриптор файла получит данные с помощью метода loop.add_reader(), а затем закрытие цикла событий:
import asyncio
from socket import socketpair
# Create a pair of connected file descriptors
rsock, wsock = socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# We are done: unregister the file descriptor
loop.remove_reader(rsock)
# Stop the event loop
loop.stop()
# Register the file descriptor for read event
loop.add_reader(rsock, reader)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
try:
# Run the event loop
loop.run_forever()
finally:
# We are done. Close sockets and the event loop.
rsock.close()
wsock.close()
loop.close()
См. также
- Аналогичный пример с использованием транспортов, протоколов и метода
loop.create_connection(). - Еще один похожий пример с использованием высокоуровневой функции
asyncio.open_connection()и потоков.
Установка обработчиков сигналов для SIGINT и SIGTERM
(Этот signals пример работает только в Unix.)
Регистрация обработчиков сигналов SIGINT и SIGTERM с помощью метода loop.add_signal_handler():
import asyncio
import functools
import os
import signal
def ask_exit(signame, loop):
print("got signal %s: exit" % signame)
loop.stop()
async def main():
loop = asyncio.get_running_loop()
for signame in {'SIGINT', 'SIGTERM'}:
loop.add_signal_handler(
getattr(signal, signame),
functools.partial(ask_exit, signame, loop))
await asyncio.sleep(3600)
print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")
asyncio.run(main())
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/library/asyncio-eventloop.html