Цикл обработки событий
Предисловие
Цикл обработки событий является ядром каждого приложения 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(), цикл опросит селектор ввода-вывода один раз с таймаутом ноль, выполнит все обратные вызовы, запланированные в ответ на события ввода-вывода (и те, которые уже были запланированы), и затем завершится.Если
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.
Планирование обратных вызовов
-
loop.call_soon(callback, *args, context=None) -
Запланировать обработчик для вызова с аргументами args на следующей итерации цикла событий.
Обработчики вызываются в порядке их регистрации. Каждый обработчик вызывается ровно один раз.
Необязательный ключевой аргумент context позволяет указать пользовательский
contextvars.Contextдля выполнения обработчика. Текущий контекст используется, если context не указан.Возвращается экземпляр
asyncio.Handle, который можно использовать для отмены обработчика позднее.Этот метод не потокобезопасен.
-
loop.call_soon_threadsafe(callback, *args, context=None) -
Потокобезопасная версия
call_soon(). Должна использоваться для планирования обработчиков из другого потока.См. раздел конкурентности и многопоточности документации.
Изменено в версии 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.7.1: В Python 3.7.0 и ранее с реализацией цикла событий по умолчанию delay не мог превышать одного дня. Это было исправлено в Python 3.7.1.
-
loop.call_at(when, callback, *args, context=None) -
Запланировать вызов callback в абсолютный момент времени when (целое или дробное число), используя ту же временную метку, что и
loop.time().Поведение этого метода такое же, как у
call_later().Возвращается экземпляр
asyncio.TimerHandle, который можно использовать для отмены вызова.Изменено в версии 3.7: Добавлен ключевой параметр context. Дополнительные сведения см. в PEP 567.
Изменено в версии 3.7.1: В Python 3.7.0 и ранее с реализацией цикла событий по умолчанию разность между when и текущим временем не могла превышать одного дня. Это было исправлено в Python 3.7.1.
-
loop.time() -
Возвращает текущее время как значение
floatв соответствии с внутренним монотонным таймером цикла событий.
Примечание
Изменено в версии 3.8: В Python 3.7 и ранее таймауты (относительная задержка delay или абсолютное время when) не должны превышать один день. Это было исправлено в Python 3.8.
См. также
Функцию asyncio.sleep().
Создание объектов Future и Task
-
loop.create_future() -
Создаёт объект
asyncio.Future, привязанный к циклу событий.Это предпочтительный способ создания объектов Future в asyncio. Это позволяет сторонним циклам событий предоставлять альтернативные реализации объекта Future (с лучшей производительностью или инструментировкой).
Добавлен в версии 3.5.2.
-
loop.create_task(coro) -
Планирует выполнение корутины. Возвращает объект
Task.Сторонние циклы событий могут использовать свои собственные подклассы
Taskдля межпрограммной совместимости. В этом случае тип результата является подклассомTask.
-
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) -
Установить соединение с потоковым транспортом по заданному адресу, указанному в host и port.
Семейство сокетов может быть либо
AF_INET, либоAF_INET6в зависимости от host (или аргумента family, если он предоставлен).Тип сокета будет
SOCK_STREAM.protocol_factory должно быть вызываемым объектом, возвращающим реализацию протокола asyncio.
Этот метод попытается установить соединение в фоновом режиме. При успехе он возвращает пару
(transport, protocol).Хронологический обзор базовой операции:
- Соединение устанавливается, и для него создается транспорт.
- protocol_factory вызывается без аргументов и ожидается, что он вернёт экземпляр протокола.
- Экземпляр протокола связывается с транспортом, вызвав его метод
connection_made(). - В случае успеха возвращается кортеж
(transport, protocol).
Созданный транспорт — это зависящий от реализации двунаправленный поток.
Другие аргументы:
-
ssl: если задано и не ложно, создаётся транспорт SSL/TLS (по умолчанию создаётся обычный TCP-транспорт). Если ssl — объект
ssl.SSLContext, этот контекст используется для создания транспорта; если ssl —True, используется контекст по умолчанию, возвращаемый изssl.create_default_context().См. также
-
server_hostname задаёт или переопределяет имя хоста, по которому будет проверяться сертификат целевого сервера. Должен быть передан только если ssl не
None. По умолчанию используется значение аргумента host. Если host пустое, по умолчанию нет значения, и вы должны передать значение для server_hostname. Если server_hostname — пустая строка, проверка имени хоста отключена (что представляет серьёзную угрозу безопасности, позволяя потенциальные атаки «человек посередине»). -
family, proto, flags — необязательные семейство адреса, протокол и флаги, которые будут переданы в getaddrinfo() для разрешения host. Если заданы, все они должны быть целыми числами из соответствующих констант модуля
socket. -
sock, если задано, должен быть существующий, уже подключенный объект
socket.socket, который будет использоваться транспортом. Если sock задано, ни host, port, family, proto, flags и local_addr не должны быть указаны. -
local_addr, если задано, это кортеж
(local_host, local_port), используемый для привязки сокета локально. local_host и local_port ищутся с помощьюgetaddrinfo(), аналогично host и port. -
ssl_handshake_timeout — (для TLS-соединения) время в секундах ожидания завершения рукопожатия TLS перед прерыванием соединения.
60.0секунд, еслиNone(по умолчанию).
Добавлен в версии 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).
В Windows с
ProactorEventLoopэтот метод не поддерживается.См. примеры протокола UDP-эхо-клиента и протокола UDP-эхо-сервера.
Изменено в версии 3.4.4: Добавлены параметры family, proto, flags, reuse_address, reuse_port, allow_broadcast и sock.
Изменено в версии 3.7.6: Параметр reuse_address больше не поддерживается из-за проблем с безопасностью.
-
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).
-
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.
Передача файлов
-
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.7: Использование исполнителя, не являющегося экземпляром
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; - ‘handle’ (необязательно): Объект
asyncio.Handle; - ‘protocol’ (необязательно): Объект Протокола;
- ‘transport’ (необязательно): Объект Транспорта;
- ‘socket’ (необязательно): Объект
socket.socket.
Примечание
Этот метод не должен перегружаться в подклассах циклов событий. Для пользовательской обработки исключений используйте метод
set_exception_handler().
Включение отладочного режима
-
loop.get_debug() -
Получить режим отладки (
bool) цикла событий.Значение по умолчанию —
Trueесли переменная окруженияPYTHONASYNCIODEBUGустановлена непустой строкой,Falseв противном случае.
-
loop.set_debug(enabled: bool) -
Установить режим отладки цикла событий.
Изменено в версии 3.7: Новый
-X devкомандная строка опция теперь также может использоваться для включения режима отладки.
См. также
Режим отладки asyncio.
Запуск дочерних процессов
Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном коде async/await используйте высокоуровневые функции asyncio.create_subprocess_shell() и asyncio.create_subprocess_exec() вместо этого.
Примечание
По умолчанию цикл событий asyncio на Windows не поддерживает дочерние процессы. Подробности см. в Поддержка дочерних процессов на 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(по умолчанию). По умолчанию будет создан и подключён новый канал. -
stdout: либо объект, подобный файлу, представляющий канал, который будет подключён к стандартному потоку вывода дочернего процесса с помощью
connect_read_pipe(), либо константаsubprocess.PIPE(по умолчанию). По умолчанию будет создан и подключён новый канал. -
stderr: либо объект, подобный файлу, представляющий канал, который будет подключён к стандартному потоку ошибок дочернего процесса с помощью
connect_read_pipe(), либо одна из константsubprocess.PIPE(по умолчанию) илиsubprocess.STDOUT.По умолчанию будет создан и подключён новый канал. Когда указана
subprocess.STDOUT, поток стандартных ошибок дочернего процесса будет подключён к тому же каналу, что и поток стандартного вывода. - Все остальные ключевые аргументы передаются в
subprocess.Popenбез интерпретации, за исключением bufsize, universal_newlines и shell, которые вообще не следует указывать.
См. конструктор класса
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, на которых сервер прослушивает, илиNone, если сервер закрыт.Изменено в версии 3.7: До Python 3.7
Server.socketsвозвращал внутренний список сокетов сервера напрямую. В 3.7 возвращается копия этого списка.
-
Реализации циклов событий
В asyncio поставляются две различные реализации циклов событий: SelectorEventLoop и ProactorEventLoop.
По умолчанию asyncio настроен на использование SelectorEventLoop на всех платформах.
-
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.
Пример использования
ProactorEventLoopв Windows:import asyncio import sys if sys.platform == 'win32': loop = asyncio.ProactorEventLoop() asyncio.set_event_loop(loop)
-
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–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.7/library/asyncio-eventloop.html