Содержание страницы
Цикл событий¶Event Loop
Исходный код: 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 цикла событий.
Методы цикла событий¶Event Loop Methods
Циклы событий имеют низкоуровневые API для следующего:
Планирование колбэковScheduling callbacks
Планирование отложенных колбэковScheduling delayed callbacks
Создание Future и задачCreating Futures and Tasks
Открытие сетевых соединенийOpening network connections
Создание сетевых серверовCreating network servers
Передача файловTransferring files
Обновление TLSTLS Upgrade
Наблюдение за файловыми дескрипторамиWatching file descriptors
Работа с объектами сокетов напрямуюWorking with socket objects directly
Работа с каналамиWorking with pipes
Сигналы UnixUnix signals
Выполнение кода в пулах потоков или процессовExecuting code in thread or process pools
API обработки ошибокError Handling API
Включение режима отладкиEnabling debug mode
Запуск подпроцессовRunning Subprocesses
Запуск и остановка цикла¶Running and stopping the loop
-
loop.run_until_complete(future)¶ Выполняется до тех пор, пока future (экземпляр
Future) не завершится.Если аргумент является объектом корутины, он неявно планируется для выполнения как
asyncio.Task.Возвращает результат Future или возбуждает его исключение.
-
loop.run_forever()¶ Запускает цикл событий до вызова
stop().Если
stop()вызывается до вызоваrun_forever(), цикл один раз опросит I/O-селектор с нулевым таймаутом, выполнит все колбэки, запланированные в ответ на события ввода-вывода (и уже запланированные), а затем завершится.Если
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.
Планирование колбэков¶Scheduling callbacks
-
loop.call_soon(callback, *args, context=None)¶ Планирует вызов колбэк колбэк с аргументами args на следующей итерации цикла событий.
Колбэки вызываются в порядке их регистрации. Каждый колбэк будет вызван ровно один раз.
Необязательный аргумент context (только ключевой) позволяет указать пользовательский
contextvars.Contextдля выполнения колбэка. Если context не указан, используется текущий контекст.Возвращается экземпляр
asyncio.Handle, который можно использовать позже для отмены колбэка.Этот метод не потокобезопасен.
-
loop.call_soon_threadsafe(callback, *args, context=None)¶ Потокобезопасный вариант
call_soon(). Должен использоваться для планирования колбэков из другого потока.Возбуждает
RuntimeError, если вызван на закрытом цикле событий. Это может произойти во вторичном потоке при завершении главного приложения.См. раздел concurrency and multithreading документации.
Изменено в версии 3.7: Добавлен параметр context (только ключевое слово). Подробнее см. PEP 567.
Примечание
Большинство функций планирования asyncio не позволяют передавать
именованные аргументы. Для этого используйте functools.partial():
# запланирует "print("Hello", flush=True)"
loop.call_soon(
functools.partial(print, "Hello", flush=True))
Использование partial-объектов обычно удобнее лямбд, так как asyncio может лучше отображать partial-объекты в сообщениях отладки и ошибок.
Планирование отложенных колбэков¶Scheduling delayed callbacks
Цикл событий предоставляет механизмы для планирования вызова функций-колбэков в некоторый момент в будущем. Цикл событий использует монотонные часы для отслеживания времени.
-
loop.call_later(delay, callback, *args, context=None)¶ Планирует вызов колбэк через заданное количество секунд delay (может быть целым числом или числом с плавающей запятой).
Возвращается экземпляр
asyncio.TimerHandle, который можно использовать для отмены колбэка.колбэк будет вызван ровно один раз. Если два колбэка запланированы на одно и то же время, порядок их вызова не определён.
Необязательные позиционные аргументы args будут переданы колбэку при его вызове. Если нужно передать колбэку именованные аргументы, используйте
functools.partial().Необязательный аргумент context (только ключевой) позволяет указать пользовательский
contextvars.Contextдля выполнения колбэка. Если context не указан, используется текущий контекст.Изменено в версии 3.7: Добавлен параметр context (только ключевое слово). Подробнее см. PEP 567.
Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией цикла событий по умолчанию параметр delay не мог превышать одного дня. В Python 3.8 это исправлено.
-
loop.call_at(when, callback, *args, context=None)¶ Планирует вызов колбэк в заданную абсолютную временную метку 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 и более ранних версиях таймауты (относительная задержка или абсолютное значение when) не должны были превышать одного дня. Это было исправлено в Python 3.8.
См. также
Функция asyncio.sleep().
Создание Future и задач¶Creating Futures and Tasks
-
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, если используется стандартная.
Открытие сетевых соединений¶Opening network connections
-
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вызовет исключение.Когда несколько процессов с разными UID назначают сокеты одному и тому же адресу UDP-сокета с помощью
SO_REUSEADDR, входящие пакеты могут случайным образом распределяться между сокетами.На поддерживаемых платформах reuse_port можно использовать как замену аналогичной функциональности. С reuse_port используется
SO_REUSEPORT, что не позволяет процессам с разными UID назначать сокеты на один и тот же адрес сокета.Создать датаграммное соединение.
Семейство сокетов может быть одним из
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.
-
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 теперь может быть path-подобным объектом.
Создание сетевых серверов¶Creating network servers
-
coroutine
loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)¶ Создаёт TCP-сервер (тип сокета
SOCK_STREAM), прослушивающий порт на адресе хоста.Возвращает объект
Server.Аргументы:
protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
Параметр host может принимать значения нескольких типов, которые определяют, где будет слушать сервер:
Если host – строка, TCP-сервер привязывается к одному сетевому интерфейсу, указанному в host.
Если host – последовательность строк, TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в этой последовательности.
Если host – пустая строка или
None, подразумеваются все интерфейсы, и будет возвращён список из нескольких сокетов (скорее всего, один для IPv4 и один для IPv6).
Параметр port можно задать, чтобы указать, какой порт должен слушать сервер. Если
0илиNone(по умолчанию), будет выбран случайный свободный порт (обратите внимание: если host разрешается в несколько сетевых интерфейсов, для каждого интерфейса будет выбран разный случайный порт).family может быть установлен в
socket.AF_INETилиAF_INET6, чтобы принудительно использовать IPv4 или IPv6. Если не задан, family будет определён по имени хоста (по умолчаниюAF_UNSPEC).flags – битовая маска для
getaddrinfo().sock может быть указан опционально, чтобы использовать уже существующий объект сокета. Если он указан, host и port не должны быть заданы.
backlog – максимальное количество соединений в очереди, передаваемое в
listen()(по умолчанию 100).ssl может быть установлен в экземпляр
SSLContextдля включения TLS для принимаемых соединений.reuse_address указывает ядру повторно использовать локальный сокет в состоянии
TIME_WAIT, не дожидаясь истечения его естественного тайм-аута. Если не указан, автоматически устанавливается вTrueна Unix.reuse_port указывает ядру разрешить привязку этой конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows.
ssl_handshake_timeout (для TLS-сервера) – время ожидания в секундах завершения TLS-рукопожатия перед разрывом соединения.
60.0секунд, еслиNone(по умолчанию).start_serving, установленный в
True(по умолчанию), заставляет созданный сервер немедленно начать принимать соединения. Если установлен вFalse, пользователь должен дождатьсяServer.start_serving()илиServer.serve_forever(), чтобы сервер начал принимать соединения.
Новое в версии 3.7: Добавлены параметры ssl_handshake_timeout и start_serving.
Изменено в версии 3.6: Параметр сокета
TCP_NODELAYтеперь устанавливается по умолчанию для всех TCP-соединений.Изменено в версии 3.5: Добавлена поддержка SSL/TLS в
ProactorEventLoop.Изменено в версии 3.5.1: Параметр host может быть последовательностью строк.
См. также
Функция
start_server()– это API более высокого уровня, который возвращает паруStreamReaderиStreamWriter, которые можно использовать в коде с async/await.
-
coroutine
loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)¶ Аналогично
loop.create_server(), но работает с семейством сокетовAF_UNIX.path – имя сокета домена Unix и является обязательным, если не передан аргумент sock. Поддерживаются абстрактные сокеты 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.
Передача файлов¶Transferring files
-
coroutine
loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)¶ Отправляет файл через транспорт. Возвращает общее количество отправленных байтов.
Метод использует высокопроизводительный
os.sendfile(), если доступен.file должен быть обычным файловым объектом, открытым в бинарном режиме.
offset указывает, с какого места начинать чтение файла. Если задан, count – это общее количество байтов для передачи, в отличие от отправки файла до достижения EOF. Позиция в файле всегда обновляется, даже если этот метод вызывает ошибку, а
file.tell()можно использовать для получения фактического количества отправленных байтов.fallback, установленный в
True, заставляет asyncio вручную читать и отправлять файл, если платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет в Unix).Вызывает
SendfileNotAvailableError, если система не поддерживает системный вызов sendfile, а fallback равенFalse.Добавлено в версии 3.7.
Обновление TLS¶TLS Upgrade
-
coroutine
loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None)¶ Обновляет существующее соединение на основе транспорта до TLS.
Возвращает новый экземпляр транспорта, который протокол должен начать использовать сразу после await. Экземпляр транспорт, переданный методу start_tls, больше не следует использовать.
Параметры:
транспорт и протокол – экземпляры, возвращаемые методами наподобие
create_server()иcreate_connection().sslcontext: настроенный экземпляр
SSLContext.server_side передавайте
Trueпри обновлении серверного соединения (например, созданногоcreate_server()).server_hostname: задаёт или переопределяет имя узла, с которым будет сверяться сертификат целевого сервера.
ssl_handshake_timeout – время в секундах, в течение которого ожидается завершение TLS-рукопожатия перед разрывом соединения (для TLS-соединений).
60.0секунд, еслиNone(по умолчанию).
Добавлено в версии 3.7.
Наблюдение за файловыми дескрипторами¶Watching file descriptors
-
loop.add_reader(fd, callback, *args)¶ Начинает наблюдение за файловым дескриптором fd на готовность к чтению и вызывает колбэк с указанными аргументами, как только fd станет доступен для чтения.
-
loop.remove_reader(fd)¶ Останавливает мониторинг файлового дескриптора fd на доступность чтения.
-
loop.add_writer(fd, callback, *args)¶ Начинает отслеживать готовность файлового дескриптора fd к записи и вызывает колбэк с указанными аргументами, как только fd становится доступным для записи.
Используйте
functools.partial()для передачи именованных аргументов в колбэк.
-
loop.remove_writer(fd)¶ Останавливает мониторинг файлового дескриптора fd на доступность записи.
См. также раздел Поддержка платформ о некоторых ограничениях этих методов.
Работа с объектами сокетов напрямую¶Working with socket objects directly
В целом реализации протоколов, использующие 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попытается проверить, разрешён ли уже 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
оба метода являются корутинами.
Работа с каналами¶Working with pipes
-
coroutine
loop.connect_read_pipe(protocol_factory, pipe)¶ Регистрирует читающий конец канала pipe в цикле событий.
protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.
pipe – это объект, подобный файлу.
Возвращает пару
(transport, protocol), где транспорт поддерживает интерфейсReadTransport, а протокол – объект, созданный фабрикой protocol_factory.При
SelectorEventLoopцикле событий канал pipe переводится в неблокирующий режим.
-
coroutine
loop.connect_write_pipe(protocol_factory, pipe)¶ Регистрирует записывающий конец канала pipe в цикле событий.
protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.
pipe – это объект, подобный файлу.
Возвращает пару
(transport, protocol), где транспорт поддерживает интерфейсWriteTransport, а протокол – объект, созданный фабрикой protocol_factory.При
SelectorEventLoopцикле событий канал pipe переводится в неблокирующий режим.
Примечание
SelectorEventLoop не поддерживает указанные выше методы в
Windows. Используйте ProactorEventLoop вместо них в Windows.
См. также
Сигналы Unix¶Unix signals
-
loop.add_signal_handler(signum, callback, *args)¶ Устанавливает колбэк в качестве обработчика сигнала signum.
Колбэк будет вызван loop вместе с другими поставленными в очередь колбэками и готовыми к запуску корутинами этого цикла событий. В отличие от обработчиков сигналов, зарегистрированных с помощью
signal.signal(), колбэк, зарегистрированный этой функцией, может взаимодействовать с циклом событий.Вызывает
ValueError, если номер сигнала недопустим или его невозможно перехватить. ВызываетRuntimeError, если возникла проблема при установке обработчика.Используйте
functools.partial()для передачи именованных аргументов в колбэк.Как и
signal.signal(), эта функция должна вызываться в главном потоке.
-
loop.remove_signal_handler(sig)¶ Удаляет обработчик сигнала sig.
Возвращает
True, если обработчик сигнала был удалён, илиFalse, если для указанного сигнала обработчик не был установлен.Доступность: Unix.
См. также
Модуль signal.
Выполнение кода в пулах потоков или процессов¶Executing code in thread or process pools
-
awaitable
loop.run_in_executor(executor, func, *args)¶ Планирует вызов func в указанном исполнителе.
Аргумент исполнитель должен быть экземпляром
concurrent.futures.ExecutorИсполнитель по умолчанию используется, если исполнитель равенNone.Пример:
import asyncio import concurrent.futures def blocking_io(): # Файловые операции (например, логирование) могут блокировать цикл событий: выполняйте их в пуле потоков. # цикл событий: выполняйте их в пуле потоков. with open('/dev/urandom', 'rb') as f: return f.read(100) def cpu_bound(): # CPU-ёмкие операции заблокируют цикл событий: # в целом предпочтительнее выполнять их в # пуле процессов. return sum(i * i for i in range(10 ** 7)) async def main(): loop = asyncio.get_running_loop() ## Варианты: # 1. Запуск в исполнителе цикла по умолчанию: result = await loop.run_in_executor( None, blocking_io) print('default thread pool', result) # 2. Запуск в пользовательском пуле потоков: with concurrent.futures.ThreadPoolExecutor() as pool: result = await loop.run_in_executor( pool, blocking_io) print('custom thread pool', result) # 3. Запуск в пользовательском пуле процессов: with concurrent.futures.ProcessPoolExecutor() as pool: result = await loop.run_in_executor( pool, cpu_bound) print('custom process pool', result) asyncio.run(main())
Этот метод возвращает объект
asyncio.Future.Используйте
functools.partial()для передачи именованных аргументов в func.Изменено в версии 3.5.3:
loop.run_in_executor()больше не настраиваетmax_workersсоздаваемого исполнителя пула потоков, оставляя настройку по умолчанию самому исполнителю пула потоков (ThreadPoolExecutor).
-
loop.set_default_executor(executor)¶ Установить исполнитель в качестве исполнителя по умолчанию, используемого
run_in_executor(). Исполнитель должен быть экземпляромThreadPoolExecutor.Устарело с версии 3.8: Использование исполнителя, не являющегося экземпляром
ThreadPoolExecutor, устарело и приведёт к ошибке в Python 3.9.Исполнитель должен быть экземпляром
concurrent.futures.ThreadPoolExecutor.
API обработки ошибок¶Error Handling 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’: сообщение об ошибке;
'исключение' (необязательно): объект исключения;
‘future’ (необязательно): экземпляр
asyncio.Future;'задача' (необязательно): экземпляр
asyncio.Task;‘handle’ (необязательно): экземпляр
asyncio.Handle;'протокол' (необязательно): экземпляр Protocol;
'транспорт' (необязательно): экземпляр Transport;
‘socket’ (необязательно): экземпляр
socket.socket;- ‘asyncgen’ (необязательно): асинхронный генератор, вызвавший
исключение.
Примечание
Этот метод не следует переопределять в подклассах циклов событий. Для настраиваемой обработки исключений используйте метод
set_exception_handler().
Включение режима отладки¶Enabling debug mode
-
loop.get_debug()¶ Возвращает режим отладки (
bool) цикла событий.Значение по умолчанию –
True, если переменная окруженияPYTHONASYNCIODEBUGимеет непустое строковое значение, иFalseв противном случае.
-
loop.set_debug(enabled: bool)¶ Устанавливает режим отладки цикла событий.
Изменено в версии 3.7: Новый режим разработки Python теперь также можно использовать для включения режима отладки.
См. также
Запуск подпроцессов¶Running Subprocesses
Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном
коде с 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), где транспорт соответствует базовому классуasyncio.SubprocessTransport, а протокол – объект, созданный фабрикой protocol_factory.
-
coroutine
loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶ Создаёт подпроцесс из cmd, который может быть строкой
strилиbytes, закодированной в кодировку файловой системы, используя синтаксис командной оболочки платформы («shell»).Это похоже на
subprocess.Popenкласс из стандартной библиотеки, вызываемый с помощьюshell=True.Параметр protocol_factory должен быть вызываемым объектом, возвращающим подкласс класса
SubprocessProtocol.Подробнее об остальных аргументах см. в
subprocess_exec().Возвращает пару из
(transport, protocol), где транспорт соответствует базовому классуSubprocessTransport, а протокол – объект, созданный фабрикой protocol_factory.
Примечание
Ответственность за то, чтобы все пробельные и специальные символы были правильно экранированы, лежит на приложении – это позволяет избежать уязвимостей инъекции команд оболочки. Для корректного экранирования пробелов и спецсимволов в строках, используемых при построении команд оболочки, можно применить функцию shlex.quote().
Дескрипторы колбэков¶Callback Handles
-
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.
-
Объекты сервера¶Server Objects
Объекты сервера создаются функциями loop.create_server(),
loop.create_unix_server(), start_server()
и start_unix_server().
Не создавайте экземпляр класса напрямую.
-
class
asyncio.Server¶ Объекты Server являются асинхронными контекстными менеджерами. При использовании в операторе
async withгарантируется, что объект Server будет закрыт и не будет принимать новые подключения после завершения оператораasync with:srv = await loop.create_server(...) async with srv: # некоторый код # На данный момент srv закрыт и больше не принимает новые соединения.
Изменено в версии 3.7: Объект Server является асинхронным контекстным менеджером начиная с Python 3.7.
-
close()¶ Прекращает обслуживание: закрывает слушающие сокеты и устанавливает атрибут
socketsвNone.Сокеты, представляющие существующие входящие клиентские подключения, остаются открытыми.
Сервер закрывается асинхронно, используйте
wait_closed()\nкорутину, чтобы дождаться закрытия сервера.
-
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приводит к закрытию сервера.Этот метод можно вызывать, если сервер уже принимает соединения. Для одного объекта Server может существовать только одна задача
serve_forever.Пример:
async def client_connected(reader, writer): # Общение с клиентом через # потоки чтения/записи. Например: await reader.readline() async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) await srv.serve_forever() asyncio.run(main('127.0.0.1', 0))
Добавлено в версии 3.7.
-
is_serving()¶ Возвращает
True, если сервер принимает новые соединения.Добавлено в версии 3.7.
-
sockets¶ Список объектов
socket.socket, которые прослушивает сервер.Изменено в версии 3.7: До Python 3.7
Server.socketsвозвращал внутренний список серверных сокетов напрямую. В версии 3.7 возвращается копия этого списка.
-
Реализации цикла событий¶Event Loop Implementations
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, использующий «порты завершения ввода-вывода» (IOCP).
Доступность: Windows.
-
class
asyncio.AbstractEventLoop¶ Абстрактный базовый класс для циклов событий, совместимых с asyncio.
Раздел Методы цикла событий перечисляет все методы, которые должна определять альтернативная реализация
AbstractEventLoop.
Примеры¶Examples
Обратите внимание, что все примеры в этом разделе намеренно показывают, как
использовать низкоуровневые API цикла событий, такие как loop.run_forever()
и loop.call_soon(). Современные приложения asyncio редко
требуют такого стиля написания; рекомендуется использовать высокоуровневые функции,
такие как asyncio.run().
Hello World с call_soon()¶Hello World with call_soon()
Пример использования метода loop.call_soon() для планирования
колбэка. Колбэк выводит "Hello World", а затем останавливает
цикл событий:
import asyncio
def hello_world(loop):
"""Колбэк для вывода 'Hello World' и остановки цикла событий"""
print('Hello World')
loop.stop()
loop = asyncio.get_event_loop()
# Запланировать вызов hello_world()
loop.call_soon(hello_world, loop)
# Блокирующий вызов прерван loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример Hello World,
созданный с помощью корутины и функции run().
Отображение текущей даты с помощью call_later()¶Display the current date with call_later()
Пример колбэка, выводящего текущую дату каждую секунду. Колбэк
использует метод loop.call_later() для повторного планирования самого себя
через 5 секунд, а затем останавливает цикл событий:
import asyncio
import datetime
def display_date(end_time, loop):
print(datetime.datetime.now())
if (loop.time() + 1.0) < end_time:
loop.call_later(1, display_date, end_time, loop)
else:
loop.stop()
loop = asyncio.get_event_loop()
# Запланировать первый вызов display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
# Блокирующий вызов прерван loop.stop()
try:
loop.run_forever()
finally:
loop.close()
См. также
Аналогичный пример с текущей датой,
созданный с помощью корутины и функции run().
Наблюдение за файловым дескриптором на события чтения¶Watch a file descriptor for read events
Ожидание, пока файловый дескриптор не получит некоторые данные, с помощью
метода loop.add_reader(), после чего цикл событий закрывается:
import asyncio
from socket import socketpair
# Создать пару связанных файловых дескрипторов
rsock, wsock = socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# Готово: отменить регистрацию файлового дескриптора
loop.remove_reader(rsock)
# Остановить цикл событий
loop.stop()
# Зарегистрировать файловый дескриптор для события чтения
loop.add_reader(rsock, reader)
# Симулировать приём данных из сети
loop.call_soon(wsock.send, 'abc'.encode())
try:
# Запустить цикл событий
loop.run_forever()
finally:
# Готово. Закрыть сокеты и цикл событий.
rsock.close()
wsock.close()
loop.close()
См. также
Аналогичный пример с использованием транспортов, протоколов и метода
loop.create_connection().Ещё один аналогичный пример с использованием высокоуровневой функции
asyncio.open_connection()и потоков данных.
Установка обработчиков сигналов SIGINT и SIGTERM¶Set signal handlers for SIGINT and 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())