Spec-Zone.ru › Python 3.12

Цикл событий

Исходный код: Lib/asyncio/events.py, Lib/asyncio/base_events.py

Предисловие

Цикл событий — основа каждого приложения asyncio. Циклы событий выполняют асинхронные задачи и обратные вызовы, выполняют операции сетевого ввода-вывода и запускают подпроцессы.

Разработчикам приложений обычно следует использовать высокоуровневые функции asyncio, например asyncio.run(), и редко обращаться к объекту цикла или вызывать его методы. Этот раздел предназначен главным образом для авторов низкоуровневого кода, библиотек и фреймворков, которым требуется более точный контроль над поведением цикла событий.

Получение цикла событий

Для получения, установки или создания цикла событий можно использовать следующие низкоуровневые функции:

asyncio.get_running_loop()

Возвращает работающий цикл событий в текущем потоке ОС.

Вызывает RuntimeError, если работающего цикла событий нет.

Эту функцию можно вызывать только из сопрограммы или обратного вызова.

Добавлено в версии 3.7.

asyncio.get_event_loop()

Получает текущий цикл событий.

При вызове из сопрограммы или обратного вызова (например, запланированного с помощью call_soon или аналогичного API) эта функция всегда возвращает работающий цикл событий.

Если работающий цикл событий не установлен, функция возвращает результат вызова get_event_loop_policy().get_event_loop().

Поскольку поведение этой функции довольно сложное (особенно при использовании пользовательских политик цикла событий), в сопрограммах и обратных вызовах предпочтительнее использовать функцию get_running_loop(), а не get_event_loop().

Как отмечалось выше, рассмотрите возможность использования высокоуровневой функции asyncio.run() вместо ручного создания и закрытия цикла событий с помощью этих низкоуровневых функций.

Устарела с версии 3.12: Если текущий цикл событий отсутствует, выдается предупреждение об устаревании. В одном из будущих выпусков Python это станет ошибкой.

asyncio.set_event_loop(loop)

Устанавливает loop в качестве текущего цикла событий для текущего потока ОС.

asyncio.new_event_loop()

Создает и возвращает новый объект цикла событий.

Обратите внимание, что поведение функций get_event_loop(), set_event_loop() и new_event_loop() можно изменить, установив пользовательскую политику цикла событий.

Содержание

Эта страница документации содержит следующие разделы:

  • В разделе Методы цикла событий приведена справочная документация по API цикла событий;
  • В разделе Объекты-обработчики обратных вызовов описаны экземпляры Handle и TimerHandle, возвращаемые методами планирования, такими как loop.call_soon() и loop.call_later();
  • В разделе Объекты сервера описаны типы, возвращаемые методами цикла событий, например loop.create_server();
  • В разделе Реализации цикла событий описаны классы SelectorEventLoop и ProactorEventLoop;
  • В разделе Примеры показано, как работать с некоторыми API цикла событий.

Методы цикла событий

Циклы событий предоставляют низкоуровневые API для выполнения следующих действий:

  • Запуск и остановка цикла
  • Планирование обратных вызовов
  • Планирование отложенных обратных вызовов
  • Создание Future и 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()

Закрывает цикл событий.

При вызове этой функции цикл не должен работать. Все ожидающие выполнения обратные вызовы будут отброшены.

Этот метод очищает все очереди и завершает работу исполнителя, но не дожидается завершения исполнителя.

Этот метод идемпотентен и необратим. После закрытия цикла событий нельзя вызывать никакие другие методы.

async loop.shutdown_asyncgens()

Планирует закрытие всех открытых в данный момент объектов асинхронного генератора с помощью вызова aclose(). После вызова этого метода цикл событий выдаст предупреждение, если будет выполнена итерация по новому асинхронному генератору. Этот метод следует использовать для надежного завершения всех запланированных асинхронных генераторов.

Обратите внимание: при использовании asyncio.run() вызывать эту функцию не нужно.

Пример:

try:
    loop.run_forever()
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Добавлено в версии 3.6.

async loop.shutdown_default_executor(timeout=None)

Планирует завершение работы исполнителя по умолчанию и ожидает, пока все потоки в ThreadPoolExecutor завершатся. После вызова этого метода использование исполнителя по умолчанию с помощью loop.run_in_executor() приведет к возникновению RuntimeError.

Параметр timeout задает время (в секундах типа float), которое предоставляется исполнителю для завершения потоков. При значении по умолчанию None исполнителю предоставляется неограниченное время.

При достижении значения timeout выдается RuntimeWarning, а исполнитель по умолчанию прекращает работу, не дожидаясь завершения своих потоков.

Примечание

Не вызывайте этот метод при использовании asyncio.run(), поскольку последняя автоматически завершает работу исполнителя по умолчанию.

Добавлено в версии 3.9.

Изменено в версии 3.12: Добавлен параметр timeout.

Планирование обратных вызовов

loop.call_soon(callback, *args, context=None)

Планирует вызов callback обратного вызова с аргументами args на следующей итерации цикла событий.

Возвращает экземпляр asyncio.Handle, который впоследствии можно использовать для отмены обратного вызова.

Обратные вызовы выполняются в порядке регистрации. Каждый обратный вызов выполняется ровно один раз.

Необязательный именованный аргумент context позволяет указать пользовательский contextvars.Context, в котором будет выполняться callback. Если context не указан, обратные вызовы используют текущий контекст.

В отличие от call_soon_threadsafe(), этот метод не является потокобезопасным.

loop.call_soon_threadsafe(callback, *args, context=None)

Потокобезопасный вариант call_soon(). При планировании обратных вызовов из другого потока необходимо использовать именно эту функцию, поскольку call_soon() не является потокобезопасным.

Эту функцию безопасно вызывать из реентерабельного контекста или обработчика сигналов, однако в таких контекстах небезопасно и бесполезно использовать возвращенный объект-обработчик.

Вызывает RuntimeError, если вызывается для закрытого цикла. Это может произойти во вторичном потоке при завершении работы основного приложения.

См. раздел документации параллелизм и многопоточность.

Изменено в версии 3.7: Добавлен параметр context. Подробнее см. PEP 567.

Примечание

Большинство функций планирования asyncio не позволяют передавать именованные аргументы. Для этого используйте functools.partial():

# will schedule "print("Hello", flush=True)"
loop.call_soon(
    functools.partial(print, "Hello", flush=True))

Использовать объекты partial обычно удобнее, чем лямбда-функции, поскольку asyncio может лучше отображать объекты partial в сообщениях отладки и об ошибках.

Планирование отложенных обратных вызовов

Цикл событий предоставляет средства для планирования вызова функций обратного вызова в будущем. Для отслеживания времени цикл событий использует монотонные часы.

loop.call_later(delay, callback, *args, context=None)

Планирует вызов callback через заданное количество секунд delay (целое число или число с плавающей точкой).

Возвращается экземпляр asyncio.TimerHandle, который можно использовать для отмены обратного вызова.

callback будет вызван ровно один раз. Если два обратных вызова запланированы на одно и то же время, порядок их вызова не определен.

Необязательные позиционные аргументы args будут переданы обратному вызову при его вызове. Если необходимо вызвать обратный вызов с именованными аргументами, используйте functools.partial().

Необязательный именованный аргумент context позволяет указать пользовательский contextvars.Context, в котором будет выполняться callback. Если context не указан, используется текущий контекст.

Изменено в версии 3.7: Добавлен параметр context. Подробнее см. PEP 567.

Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией цикла событий по умолчанию значение delay не могло превышать один день. Это ограничение устранено в Python 3.8.

loop.call_at(when, callback, *args, context=None)

Планирует вызов callback в заданный абсолютный момент времени when (целое число или число с плавающей точкой), используя ту же систему отсчета времени, что и loop.time().

Этот метод работает так же, как call_later().

Возвращается экземпляр asyncio.TimerHandle, который можно использовать для отмены обратного вызова.

Изменено в версии 3.7: Добавлен параметр context. Подробнее см. PEP 567.

Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией цикла событий по умолчанию разница между when и текущим временем не могла превышать один день. Это ограничение устранено в Python 3.8.

loop.time()

Возвращает текущее время в виде значения типа float согласно внутренним монотонным часам цикла событий.

Примечание

Изменено в версии 3.8: В Python 3.7 и более ранних версиях значение тайм-аута (относительное delay или абсолютное when) не должно было превышать один день. Это ограничение устранено в Python 3.8.

См. также

Функцию asyncio.sleep().

Создание Future и Task

loop.create_future()

Создает объект asyncio.Future, связанный с циклом событий.

Это предпочтительный способ создания Future в asyncio. Благодаря этому сторонние циклы событий могут предоставлять альтернативные реализации объекта Future (с более высокой производительностью или дополнительными средствами инструментирования).

Добавлено в версии 3.5.2.

loop.create_task(coro, *, name=None, context=None)

Планирует выполнение сопрограммы coro. Возвращает объект Task.

Для обеспечения совместимости сторонние циклы событий могут использовать собственный подкласс Task. В этом случае результат будет экземпляром подкласса Task.

Если задан аргумент name и он не равен None, он устанавливается в качестве имени задачи с помощью Task.set_name().

Необязательный именованный аргумент context позволяет указать пользовательский contextvars.Context, в котором будет выполняться coro. Если context не указан, создается копия текущего контекста.

Изменено в версии 3.8: Добавлен параметр name.

Изменено в версии 3.11: Добавлен параметр context.

loop.set_task_factory(factory)

Устанавливает фабрику задач, которая будет использоваться методом loop.create_task().

Если factory равен None, будет установлена фабрика задач по умолчанию. В противном случае factory должен быть вызываемым объектом с сигнатурой, соответствующей (loop, coro, context=None), где loop — ссылка на активный цикл событий, а coro — объект сопрограммы. Вызываемый объект должен возвращать объект, совместимый с asyncio.Future.

loop.get_task_factory()

Возвращает фабрику задач или None, если используется фабрика по умолчанию.

Открытие сетевых подключений

async loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, happy_eyeballs_delay=None, interleave=None, all_errors=False)

Открыть потоковое транспортное подключение по адресу, указанному параметрами host и port.

Семейство сокетов может быть AF_INET или AF_INET6 в зависимости от host (или аргумента family, если он указан).

Тип сокета будет SOCK_STREAM.

protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.

Этот метод попытается установить подключение в фоновом режиме. В случае успеха он возвращает пару (transport, protocol).

Хронологическое описание базовой операции:

  1. Устанавливается подключение и для него создаётся транспорт.
  2. Вызывается protocol_factory без аргументов; ожидается, что он вернёт экземпляр протокола.
  3. Экземпляр протокола связывается с транспортом вызовом метода connection_made().
  4. В случае успеха возвращается кортеж (transport, protocol).

Созданный транспорт представляет собой двунаправленный поток; его реализация зависит от конкретной системы.

Другие аргументы:

  • ssl: если аргумент задан и имеет истинное значение, создаётся транспорт SSL/TLS (по умолчанию создаётся обычный транспорт TCP). Если ssl — объект ssl.SSLContext, для создания транспорта используется этот контекст; если ssl — True, используется контекст по умолчанию, возвращаемый функцией ssl.create_default_context().

    См. также

    Рекомендации по безопасности SSL/TLS

  • server_hostname задаёт или переопределяет имя хоста, с которым будет сравниваться сертификат целевого сервера. Этот аргумент следует передавать, только если ssl не равно None. По умолчанию используется значение аргумента host. Если host пуст, значение по умолчанию отсутствует, и необходимо передать значение для server_hostname. Если server_hostname — пустая строка, проверка соответствия имени хоста отключается (это создаёт серьёзный риск для безопасности и может привести к атакам типа «человек посередине»).
  • family, proto, flags — необязательные семейство адресов, протокол и флаги, передаваемые в getaddrinfo() для разрешения имени host. Если они указаны, все эти значения должны быть целыми числами — соответствующими константами модуля socket.
  • happy_eyeballs_delay, если указан, включает алгоритм Happy Eyeballs для этого подключения. Значение должно быть числом с плавающей точкой, обозначающим время в секундах ожидания завершения попытки подключения перед параллельным запуском следующей попытки. Это «задержка между попытками подключения», определённая в RFC 8305. Рекомендуемое RFC разумное значение по умолчанию — 0.25 (250 миллисекунд).
  • interleave управляет переупорядочиванием адресов, когда имя хоста разрешается в несколько IP-адресов. Если указано 0 или значение не задано, переупорядочивание не выполняется, а адреса проверяются в порядке, возвращённом функцией getaddrinfo(). Если указано положительное целое число, адреса чередуются по семействам адресов, а указанное целое число интерпретируется как «количество адресов первого семейства», определённое в RFC 8305. По умолчанию используется 0, если happy_eyeballs_delay не задан, и 1, если он задан.
  • sock, если указан, должен быть существующим, уже подключённым объектом socket.socket, который будет использоваться транспортом. Если указан sock, не следует задавать host, port, family, proto, flags, happy_eyeballs_delay, interleave и local_addr.

    Примечание

    Аргумент sock передаёт созданному транспорту владение сокетом. Чтобы закрыть сокет, вызовите метод close() транспорта.

  • local_addr, если указан, представляет собой кортеж (local_host, local_port), используемый для привязки сокета к локальному адресу. Значения local_host и local_port определяются с помощью getaddrinfo(), аналогично host и port.
  • ssl_handshake_timeout — время в секундах (для подключения TLS), в течение которого ожидается завершение рукопожатия TLS до прерывания подключения. 60.0 секунд, если указано None (значение по умолчанию).
  • ssl_shutdown_timeout — время в секундах ожидания завершения отключения SSL до прерывания подключения. 30.0 секунд, если указано None (значение по умолчанию).
  • all_errors определяет, какие исключения вызываются, если не удаётся создать подключение. По умолчанию вызывается только одно исключение Exception: первое, если ошибка всего одна или все ошибки имеют одинаковое сообщение, либо одно исключение OSError с объединёнными сообщениями об ошибках. Если all_errors имеет значение True, будет вызвано исключение ExceptionGroup, содержащее все исключения (даже если оно всего одно).

Изменено в версии 3.5: Добавлена поддержка SSL/TLS в ProactorEventLoop.

Изменено в версии 3.6: Для всех подключений TCP по умолчанию устанавливается параметр сокета socket.TCP_NODELAY.

Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.

Изменено в версии 3.8: Добавлены параметры happy_eyeballs_delay и interleave.

Алгоритм Happy Eyeballs: успешная работа с узлами с двойным стеком. Если путь и протокол IPv4 сервера работают, а путь и протокол IPv6 — нет, клиентское приложение с двойным стеком испытывает значительную задержку подключения по сравнению с клиентом, использующим только IPv4. Это нежелательно, поскольку ухудшает пользовательский опыт при работе с клиентом с двойным стеком. В этом документе определены требования к алгоритмам, уменьшающим такую заметную для пользователя задержку, и представлен один из таких алгоритмов.

Дополнительная информация: https://datatracker.ietf.org/doc/html/rfc6555

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Изменено в версии 3.12: Добавлен параметр all_errors.

См. также

Функция open_connection() представляет собой альтернативный высокоуровневый API. Она возвращает пару (StreamReader, StreamWriter), которую можно использовать непосредственно в коде async/await.

async loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_port=None, allow_broadcast=None, sock=None)

Создать дейтаграммное подключение.

Семейство сокетов может быть AF_INET, AF_INET6 или AF_UNIX в зависимости от host (или аргумента family, если он указан).

Тип сокета будет SOCK_DGRAM.

protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.

В случае успеха возвращается кортеж из (transport, protocol).

Другие аргументы:

  • local_addr, если указан, представляет собой кортеж (local_host, local_port), используемый для привязки сокета к локальному адресу. Значения local_host и local_port определяются с помощью getaddrinfo().
  • remote_addr, если указан, представляет собой кортеж (remote_host, remote_port), используемый для подключения сокета к удалённому адресу. Значения remote_host и remote_port определяются с помощью getaddrinfo().
  • family, proto, flags — необязательные семейство адресов, протокол и флаги, передаваемые в getaddrinfo() для разрешения имени host. Если они указаны, все эти значения должны быть целыми числами — соответствующими константами модуля socket.
  • reuse_port указывает ядру разрешить привязку этой конечной точки к тому же порту, что и у других существующих конечных точек, при условии, что при их создании для всех был установлен этот флаг. Этот параметр не поддерживается в Windows и некоторых системах Unix. Если константа socket.SO_REUSEPORT не определена, эта возможность не поддерживается.
  • allow_broadcast указывает ядру разрешить этой конечной точке отправлять сообщения на широковещательный адрес.
  • sock можно указать, чтобы использовать существующий, уже подключённый объект socket.socket в качестве транспорта. Если он указан, аргументы local_addr и remote_addr следует опустить (они должны иметь значение None).

    Примечание

    Аргумент sock передаёт созданному транспорту владение сокетом. Чтобы закрыть сокет, вызовите метод close() транспорта.

См. примеры протокола UDP-клиента эхо-сервера и протокола UDP-сервера эхо-сервера.

Изменено в версии 3.4.4: Добавлены параметры family, proto, flags, reuse_address, reuse_port, allow_broadcast и sock.

Изменено в версии 3.8: Добавлена поддержка Windows.

Изменено в версии 3.8.1: Параметр reuse_address больше не поддерживается, поскольку использование socket.SO_REUSEADDR создаёт значительный риск для безопасности UDP. При явной передаче reuse_address=True будет вызвано исключение.

Если несколько процессов с разными UID привязывают сокеты к одному и тому же адресу UDP-сокета с помощью SO_REUSEADDR, входящие пакеты могут случайным образом распределяться между сокетами.

На поддерживаемых платформах вместо аналогичной функциональности можно использовать reuse_port. При использовании reuse_port применяется socket.SO_REUSEPORT, который специально предотвращает привязку сокетов к одному адресу сокета процессами с разными UID.

Изменено в версии 3.11: Параметр reuse_address, отключённый начиная с Python 3.8.1, 3.7.6 и 3.6.10, полностью удалён.

async loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Создать подключение Unix.

Семейство сокетов — AF_UNIX; тип сокета — SOCK_STREAM.

В случае успеха возвращается кортеж из (transport, protocol).

path — имя доменного сокета Unix; этот аргумент обязателен, если не указан параметр sock. Поддерживаются абстрактные сокеты Unix, пути типа str, bytes и Path.

Информацию об аргументах этого метода см. в документации метода loop.create_connection().

Доступность: Unix.

Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout. Теперь параметр path может быть объектом, подобным пути.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Создание сетевых серверов

async loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)

Создать TCP-сервер (тип сокета SOCK_STREAM), прослушивающий адрес host и порт port.

Возвращает объект Server.

Аргументы:

  • protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
  • Параметру host можно присвоить несколько типов значений, которые определяют, на каких адресах будет прослушиваться сервер:

    • Если host — строка, TCP-сервер привязывается к одному сетевому интерфейсу, указанному в host.
    • Если host — последовательность строк, TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в последовательности.
    • Если host — пустая строка или None, используются все интерфейсы и возвращается список из нескольких сокетов (скорее всего, один для IPv4 и другой для IPv6).
  • Параметр port задаёт порт, который сервер должен прослушивать. Если указано 0 или None (значение по умолчанию), будет выбран случайный свободный порт (обратите внимание: если имя host разрешается в несколько сетевых интерфейсов, для каждого интерфейса будет выбран отдельный случайный порт).
  • Для параметра family можно задать socket.AF_INET или AF_INET6, чтобы принудительно использовать IPv4 или IPv6. Если значение не задано, семейство family определяется по имени хоста (по умолчанию используется AF_UNSPEC).
  • flags — битовая маска для getaddrinfo().
  • sock можно указать, чтобы использовать существующий объект сокета. Если он указан, задавать host и port нельзя.

    Примечание

    Аргумент sock передаёт созданному серверу владение сокетом. Чтобы закрыть сокет, вызовите метод close() сервера.

  • backlog — максимальное число соединений в очереди, передаваемое функции listen() (по умолчанию — 100).
  • Для включения TLS в принятых подключениях параметру ssl можно присвоить экземпляр SSLContext.
  • reuse_address указывает ядру повторно использовать локальный сокет в состоянии TIME_WAIT, не дожидаясь окончания естественного тайм-аута. Если параметр не указан, в Unix ему автоматически присваивается True.
  • reuse_port указывает ядру разрешить привязку этой конечной точки к тому же порту, что и у других существующих конечных точек, при условии, что при их создании для всех был установлен этот флаг. Этот параметр не поддерживается в Windows.
  • ssl_handshake_timeout — время в секундах ожидания завершения рукопожатия TLS до прерывания подключения (для TLS-сервера). 60.0 секунд, если указано None (значение по умолчанию).
  • ssl_shutdown_timeout — время в секундах ожидания завершения отключения SSL до прерывания подключения. 30.0 секунд, если указано None (значение по умолчанию).
  • Если для параметра start_serving задано True (значение по умолчанию), созданный сервер сразу начинает принимать подключения. Если задано False, пользователь должен дождаться выполнения Server.start_serving() или Server.serve_forever(), чтобы сервер начал принимать подключения.

Изменено в версии 3.5: Добавлена поддержка SSL/TLS в ProactorEventLoop.

Изменено в версии 3.5.1: Параметр host может быть последовательностью строк.

Изменено в версии 3.6: Добавлены параметры ssl_handshake_timeout и start_serving. Для всех подключений TCP по умолчанию устанавливается параметр сокета socket.TCP_NODELAY.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

См. также

Функция start_server() представляет собой альтернативный API более высокого уровня, возвращающий пару из StreamReader и StreamWriter, которые можно использовать в коде async/await.

async loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)

Аналогичен loop.create_server(), но работает с семейством сокетов AF_UNIX.

path — имя доменного сокета Unix; этот аргумент обязателен, если не указан аргумент sock. Поддерживаются абстрактные сокеты Unix, пути типа str, bytes и Path.

Информацию об аргументах этого метода см. в документации метода loop.create_server().

Доступность: Unix.

Изменено в версии 3.7: Добавлены параметры ssl_handshake_timeout и start_serving. Теперь параметр path может быть объектом Path.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

async loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Обеспечить уже принятое подключение парой «транспорт/протокол».

Этот метод можно использовать на серверах, принимающих подключения вне asyncio, но использующих asyncio для их обработки.

Параметры:

  • protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола.
  • sock — существующий объект сокета, возвращённый методом socket.accept.

    Примечание

    Аргумент sock передаёт созданному транспорту владение сокетом. Чтобы закрыть сокет, вызовите метод close() транспорта.

  • Для включения SSL в принятых подключениях параметру ssl можно присвоить экземпляр SSLContext.
  • ssl_handshake_timeout — время в секундах ожидания завершения рукопожатия SSL до прерывания подключения (для подключения SSL). 60.0 секунд, если указано None (значение по умолчанию).
  • ssl_shutdown_timeout — время в секундах ожидания завершения отключения SSL до прерывания подключения. 30.0 секунд, если указано None (значение по умолчанию).

Возвращает пару (transport, protocol).

Добавлено в версии 3.5.3.

Изменено в версии 3.7: Добавлен параметр ssl_handshake_timeout.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Передача файлов

async 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

async loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Обновить существующее соединение на основе транспорта до TLS.

Создать экземпляр кодировщика/декодировщика TLS и вставить его между транспортом и протоколом. Кодировщик/декодировщик реализует как протокол для транспорта, так и транспорт для протокола.

Вернуть созданный экземпляр с двумя интерфейсами. После await протокол должен перестать использовать исходный транспорт и взаимодействовать только с возвращённым объектом, поскольку кодировщик кэширует данные со стороны протокола и время от времени обменивается дополнительными пакетами сеанса TLS с транспортом.

В некоторых ситуациях (например, когда переданный транспорт уже закрывается) может быть возвращено None.

Параметры:

  • Экземпляры transport и protocol, которые возвращают такие методы, как create_server() и create_connection().
  • sslcontext: настроенный экземпляр SSLContext.
  • server_side: передайте True, если обновляется соединение на стороне сервера (например, соединение, созданное методом create_server()).
  • server_hostname: задаёт или переопределяет имя узла, с которым будет сопоставляться сертификат целевого сервера.
  • ssl_handshake_timeout — время в секундах, в течение которого ожидается завершение рукопожатия TLS перед прерыванием соединения. 60.0 секунд, если указано None (значение по умолчанию).
  • ssl_shutdown_timeout — время в секундах, в течение которого ожидается завершение закрытия SSL перед прерыванием соединения. 30.0 секунд, если указано None (значение по умолчанию).

Добавлено в версии 3.7.

Изменено в версии 3.11: Добавлен параметр ssl_shutdown_timeout.

Наблюдение за файловыми дескрипторами

loop.add_reader(fd, callback, *args)

Начать наблюдение за файловым дескриптором fd на предмет доступности для чтения и вызвать callback с указанными аргументами, когда fd станет доступен для чтения.

Все ранее зарегистрированные для fd обратные вызовы отменяются и заменяются на callback.

loop.remove_reader(fd)

Прекратить наблюдение за файловым дескриптором fd на предмет доступности для чтения. Возвращает True, если ранее за fd наблюдали для чтения.

loop.add_writer(fd, callback, *args)

Начать наблюдение за файловым дескриптором fd на предмет доступности для записи и вызвать callback с указанными аргументами, когда fd станет доступен для записи.

Все ранее зарегистрированные для fd обратные вызовы отменяются и заменяются на callback.

Используйте functools.partial() для передачи именованных аргументов в callback.

loop.remove_writer(fd)

Прекратить наблюдение за файловым дескриптором fd на предмет доступности для записи. Возвращает True, если ранее за fd наблюдали для записи.

О некоторых ограничениях этих методов см. также раздел Поддержка платформ.

Непосредственная работа с объектами сокетов

В целом реализации протоколов, использующие API на основе транспорта, такие как loop.create_connection() и loop.create_server(), работают быстрее реализаций, которые непосредственно работают с сокетами. Однако в некоторых случаях производительность не критична, а непосредственная работа с объектами socket удобнее.

async loop.sock_recv(sock, nbytes)

Получить до nbytes байт из sock. Асинхронный вариант socket.recv().

Возвращает полученные данные в виде объекта bytes.

sock должен быть неблокирующим сокетом.

Изменено в версии 3.7: Хотя в документации этот метод всегда описывался как метод-корутина, в выпусках до Python 3.7 он возвращал Future. Начиная с Python 3.7 это метод async def.

async loop.sock_recv_into(sock, buf)

Получить данные из sock в буфер buf. Метод создан по образцу блокирующего метода socket.recv_into().

Возвращает количество байт, записанных в буфер.

sock должен быть неблокирующим сокетом.

Добавлено в версии 3.7.

async loop.sock_recvfrom(sock, bufsize)

Получить из sock датаграмму размером до bufsize. Асинхронный вариант socket.recvfrom().

Возвращает кортеж (полученные данные, удалённый адрес).

sock должен быть неблокирующим сокетом.

Добавлено в версии 3.11.

async loop.sock_recvfrom_into(sock, buf, nbytes=0)

Получить из sock датаграмму размером до nbytes в buf. Асинхронный вариант socket.recvfrom_into().

Возвращает кортеж (количество полученных байт, удалённый адрес).

sock должен быть неблокирующим сокетом.

Добавлено в версии 3.11.

async loop.sock_sendall(sock, data)

Отправить data в сокет sock. Асинхронный вариант socket.sendall().

Этот метод продолжает отправлять данные в сокет, пока все данные из data не будут отправлены или не произойдёт ошибка. В случае успеха возвращается None. В случае ошибки возникает исключение. Кроме того, невозможно определить, какое количество данных, если таковое имеется, было успешно обработано принимающей стороной соединения.

sock должен быть неблокирующим сокетом.

Изменено в версии 3.7: Хотя в документации этот метод всегда описывался как метод-корутина, до Python 3.7 он возвращал Future. Начиная с Python 3.7 это метод async def.

async loop.sock_sendto(sock, data, address)

Отправить датаграмму из sock по адресу address. Асинхронный вариант socket.sendto().

Возвращает количество отправленных байт.

sock должен быть неблокирующим сокетом.

Добавлено в версии 3.11.

async loop.sock_connect(sock, address)

Подключить sock к удалённому сокету по адресу address.

Асинхронный вариант socket.connect().

sock должен быть неблокирующим сокетом.

Изменено в версии 3.5.2: address больше не требуется разрешать. sock_connect попытается проверить, разрешён ли уже адрес address, вызвав socket.inet_pton(). Если нет, для разрешения адреса address будет использован loop.getaddrinfo().

См. также

loop.create_connection() и asyncio.open_connection().

async loop.sock_accept(sock)

Принять соединение. Метод создан по образцу блокирующего метода socket.accept().

Сокет должен быть привязан к адресу и ожидать входящих соединений. Возвращаемое значение — пара (conn, address), где conn — новый объект сокета, который можно использовать для отправки и получения данных по соединению, а address — адрес, к которому привязан сокет на другом конце соединения.

sock должен быть неблокирующим сокетом.

Изменено в версии 3.7: Хотя в документации этот метод всегда описывался как метод-корутина, до Python 3.7 он возвращал Future. Начиная с Python 3.7 это метод async def.

См. также

loop.create_server() и start_server().

async loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)

Отправить файл с помощью высокопроизводительного os.sendfile, если это возможно. Возвращает общее количество отправленных байт.

Асинхронный вариант socket.sendfile().

sock должен быть неблокирующим сокетом socket.SOCK_STREAM socket.

file должен быть обычным файловым объектом, открытым в двоичном режиме.

offset задаёт начальную позицию чтения файла. Если он указан, count задаёт общее количество байт для передачи, вместо отправки файла до достижения EOF. Позиция в файле обновляется всегда, даже если этот метод вызывает ошибку; для получения фактического количества отправленных байт можно использовать file.tell().

Если fallback имеет значение True, asyncio вручную читает и отправляет файл, когда платформа не поддерживает системный вызов sendfile (например, в Windows или при использовании SSL-сокета в Unix).

Вызывает SendfileNotAvailableError, если система не поддерживает системный вызов sendfile, а fallback имеет значение False.

sock должен быть неблокирующим сокетом.

Добавлено в версии 3.7.

DNS

async loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)

Асинхронный вариант socket.getaddrinfo().

async loop.getnameinfo(sockaddr, flags=0)

Асинхронный вариант socket.getnameinfo().

Примечание

Методы getaddrinfo и getnameinfo внутри используют синхронные версии через исполнитель потоков по умолчанию цикла событий. Когда этот исполнитель перегружен, работа этих методов может задерживаться, что высокоуровневые сетевые библиотеки могут отображать как увеличение времени ожидания. Чтобы смягчить эту проблему, рассмотрите возможность использования пользовательского исполнителя для других пользовательских задач или настройки исполнителя по умолчанию с большим количеством рабочих потоков.

Изменено в версии 3.7: В документации методы getaddrinfo и getnameinfo всегда описывались как возвращающие корутину, но до Python 3.7 они фактически возвращали объекты asyncio.Future. Начиная с Python 3.7 оба метода являются корутинами.

Работа с каналами

async loop.connect_read_pipe(protocol_factory, pipe)

Зарегистрировать читающий конец pipe в цикле событий.

protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.

pipe — это объект, подобный файлу.

Возвращает пару (transport, protocol), где transport поддерживает интерфейс ReadTransport, а protocol — объект, созданный protocol_factory.

В цикле событий SelectorEventLoop для pipe устанавливается неблокирующий режим.

async loop.connect_write_pipe(protocol_factory, pipe)

Зарегистрировать пишущий конец pipe в цикле событий.

protocol_factory должен быть вызываемым объектом, возвращающим реализацию протокола asyncio.

pipe — это объект, подобный файлу.

Возвращает пару (transport, protocol), где transport поддерживает интерфейс WriteTransport, а protocol — объект, созданный protocol_factory.

В цикле событий SelectorEventLoop для pipe устанавливается неблокирующий режим.

Примечание

SelectorEventLoop не поддерживает указанные выше методы в Windows. В Windows вместо него используйте ProactorEventLoop.

См. также

Методы loop.subprocess_exec() и loop.subprocess_shell().

Сигналы 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, используется исполнитель по умолчанию. Исполнитель по умолчанию можно задать с помощью loop.set_default_executor(); в противном случае concurrent.futures.ThreadPoolExecutor будет создан при необходимости и использован методом run_in_executor().

Пример:

import asyncio
import concurrent.futures

def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

def cpu_bound():
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    return sum(i * i for i in range(10 ** 7))

async def main():
    loop = asyncio.get_running_loop()

    ## Options:

    # 1. Run in the default loop's executor:
    result = await loop.run_in_executor(
        None, blocking_io)
    print('default thread pool', result)

    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, blocking_io)
        print('custom thread pool', result)

    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom process pool', result)

if __name__ == '__main__':
    asyncio.run(main())

Обратите внимание: для варианта 3 требуется защита точки входа (if __name__ == '__main__') из-за особенностей multiprocessing, используемого ProcessPoolExecutor. См. раздел Безопасный импорт главного модуля.

Этот метод возвращает объект asyncio.Future.

Используйте functools.partial() для передачи именованных аргументов в func.

Изменено в версии 3.5.3: loop.run_in_executor() больше не настраивает max_workers создаваемого им исполнителя пула потоков, оставляя установку значения по умолчанию самому исполнителю пула потоков (ThreadPoolExecutor).

loop.set_default_executor(executor)

Задать executor в качестве исполнителя по умолчанию, используемого методом run_in_executor(). executor должен быть экземпляром ThreadPoolExecutor.

Изменено в версии 3.11: executor должен быть экземпляром ThreadPoolExecutor.

API обработки ошибок

Позволяет настраивать обработку исключений в цикле событий.

loop.set_exception_handler(handler)

Задать handler в качестве нового обработчика исключений цикла событий.

Если handler равен None, будет задан обработчик исключений по умолчанию. В противном случае handler должен быть вызываемым объектом с сигнатурой, соответствующей (loop, context), где loop — ссылка на активный цикл событий, а context — объект dict, содержащий сведения об исключении (подробности о контексте см. в документации call_exception_handler()).

Если обработчик вызывается от имени Task или Handle, он выполняется в contextvars.Context этой задачи или дескриптора обратного вызова.

Изменено в версии 3.12: Обработчик может вызываться в Context задачи или дескриптора, в котором возникло исключение.

loop.get_exception_handler()

Возвращает текущий обработчик исключений или None, если пользовательский обработчик исключений не задан.

Добавлено в версии 3.5.2.

loop.default_exception_handler(context)

Обработчик исключений по умолчанию.

Вызывается, когда происходит исключение и обработчик исключений не задан. Его может вызвать пользовательский обработчик исключений, который передаёт обработку обработчику по умолчанию.

Параметр context имеет то же значение, что и в call_exception_handler().

loop.call_exception_handler(context)

Вызвать текущий обработчик исключений цикла событий.

context — объект dict, содержащий следующие ключи (в будущих версиях Python могут появиться новые ключи):

  • ‘message’: сообщение об ошибке;
  • ‘exception’ (необязательный): объект исключения;
  • ‘future’ (необязательный): экземпляр asyncio.Future;
  • ‘task’ (необязательный): экземпляр asyncio.Task;
  • ‘handle’ (необязательный): экземпляр asyncio.Handle;
  • ‘protocol’ (необязательный): экземпляр протокола;
  • ‘transport’ (необязательный): экземпляр транспорта;
  • ‘socket’ (необязательный): экземпляр socket.socket;
  • ‘asyncgen’ (необязательный): асинхронный генератор, вызвавший

    исключение.

Примечание

Этот метод не следует переопределять в подклассах циклов событий. Для пользовательской обработки исключений используйте метод set_exception_handler().

Включение режима отладки

loop.get_debug()

Получить режим отладки (bool) цикла событий.

Значение по умолчанию — True, если переменная среды PYTHONASYNCIODEBUG задана непустой строкой, и False в противном случае.

loop.set_debug(enabled: bool)

Установить режим отладки цикла событий.

Изменено в версии 3.7: Теперь для включения режима отладки также можно использовать новый режим разработки Python.

loop.slow_callback_duration

С помощью этого атрибута можно задать минимальную длительность выполнения в секундах, при превышении которой операция считается «медленной». Если включён режим отладки, «медленные» обратные вызовы заносятся в журнал.

Значение по умолчанию — 100 миллисекунд.

См. также

Режим отладки asyncio.

Запуск подпроцессов

Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном коде с async/await рассмотрите возможность использования вместо них высокоуровневых функций-обёрток asyncio.create_subprocess_shell() и asyncio.create_subprocess_exec().

Примечание

В Windows цикл событий по умолчанию ProactorEventLoop поддерживает подпроцессы, а SelectorEventLoop — нет. Подробности см. в разделе Поддержка подпроцессов в Windows.

async 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 может принимать одно из следующих значений:

    • файлоподобный объект
    • существующий файловый дескриптор (положительное целое число), например созданный с помощью os.pipe()
    • константа subprocess.PIPE (по умолчанию), которая создаёт новый канал и подключает его;
    • значение None, которое заставляет подпроцесс наследовать файловый дескриптор этого процесса;
    • константа subprocess.DEVNULL, указывающая, что будет использоваться специальный файл os.devnull.
  • stdout может принимать одно из следующих значений:

    • файлоподобный объект
    • константа subprocess.PIPE (по умолчанию), которая создаёт новый канал и подключает его;
    • значение None, которое заставляет подпроцесс наследовать файловый дескриптор этого процесса;
    • константа subprocess.DEVNULL, указывающая, что будет использоваться специальный файл os.devnull.
  • stderr может принимать одно из следующих значений:

    • файлоподобный объект
    • константа subprocess.PIPE (по умолчанию), которая создаёт новый канал и подключает его;
    • значение None, которое заставляет подпроцесс наследовать файловый дескриптор этого процесса;
    • константа subprocess.DEVNULL, указывающая, что будет использоваться специальный файл os.devnull;
    • константа subprocess.STDOUT, которая подключает стандартный поток ошибок к стандартному потоку вывода процесса.
  • Все остальные именованные аргументы без интерпретации передаются в subprocess.Popen, кроме bufsize, universal_newlines, shell, text, encoding и errors: их указывать нельзя.

    API подпроцессов asyncio не поддерживает декодирование потоков в текст. Для преобразования байтов, полученных из потока, в текст можно использовать bytes.decode().

Если файлоподобный объект, переданный в stdin, stdout или stderr, представляет собой канал, его другой конец следует зарегистрировать с помощью connect_write_pipe() или connect_read_pipe() для использования с циклом событий.

Документацию по другим аргументам см. в описании конструктора класса subprocess.Popen.

Возвращает пару объектов (transport, protocol), где transport соответствует базовому классу asyncio.SubprocessTransport, а protocol — объект, созданный с помощью protocol_factory.

async 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().

get_context()

Возвращает объект contextvars.Context, связанный с дескриптором.

Добавлено в версии 3.12.

cancel()

Отменяет обратный вызов. Если обратный вызов уже отменён или выполнен, этот метод ничего не делает.

cancelled()

Возвращает True, если обратный вызов был отменён.

Добавлено в версии 3.7.

class asyncio.TimerHandle

Объект-обёртка для обратного вызова, возвращаемый функциями loop.call_later() и loop.call_at().

Этот класс является подклассом Handle.

when()

Возвращает время запланированного обратного вызова в секундах типа float.

Время представляет собой абсолютную метку времени с тем же началом отсчёта, что и у loop.time().

Добавлено в версии 3.7.

Объекты сервера

Объекты сервера создаются функциями loop.create_server(), loop.create_unix_server(), start_server() и start_unix_server().

Не создавайте экземпляры класса Server напрямую.

class asyncio.Server

Объекты Server являются асинхронными менеджерами контекста. При использовании в операторе async with гарантируется, что по завершении оператора async with объект Server будет закрыт и перестанет принимать новые соединения:

srv = await loop.create_server(...)

async with srv:
    # some code

# At this point, srv is closed and no longer accepts new connections.

Изменено в версии 3.7: Начиная с Python 3.7 объект Server является асинхронным менеджером контекста.

Изменено в версии 3.11: Этот класс стал общедоступным под именем asyncio.Server в Python 3.9.11, 3.10.3 и 3.11.

close()

Прекращает обслуживание: закрывает слушающие сокеты и устанавливает атрибут sockets в значение None.

Сокеты, представляющие существующие входящие клиентские соединения, остаются открытыми.

Сервер закрывается асинхронно; используйте корутину wait_closed(), чтобы дождаться закрытия сервера (и завершения всех соединений).

get_loop()

Возвращает цикл событий, связанный с объектом сервера.

Добавлено в версии 3.7.

async start_serving()

Начинает принимать соединения.

Этот метод идемпотентен, поэтому его можно вызвать, даже если сервер уже обслуживает запросы.

Параметр start_serving, задаваемый только по имени, в функциях loop.create_server() и asyncio.start_server() позволяет создать объект Server, который изначально не принимает соединения. В этом случае для начала приёма соединений объектом Server можно использовать Server.start_serving() или Server.serve_forever().

Добавлено в версии 3.7.

async serve_forever()

Начинает принимать соединения и продолжает это делать, пока корутина не будет отменена. Отмена задачи serve_forever приводит к закрытию сервера.

Этот метод можно вызвать, даже если сервер уже принимает соединения. Для одного объекта Server может существовать только одна задача serve_forever.

Пример:

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.

async wait_closed()

Ожидает завершения метода close() и закрытия всех активных соединений.

sockets

Список объектов, подобных сокетам, asyncio.trsock.TransportSocket, на которых сервер ожидает соединения.

Изменено в версии 3.7: До Python 3.7 Server.sockets возвращал непосредственно внутренний список серверных сокетов. В версии 3.7 возвращается копия этого списка.

Реализации цикла событий

В asyncio входят две различные реализации цикла событий: SelectorEventLoop и ProactorEventLoop.

По умолчанию asyncio настроен на использование SelectorEventLoop в Unix и ProactorEventLoop в Windows.

class asyncio.SelectorEventLoop

Цикл событий, основанный на модуле selectors.

Использует наиболее эффективный селектор, доступный на данной платформе. Также можно вручную настроить конкретную реализацию селектора:

import asyncio
import selectors

class MyPolicy(asyncio.DefaultEventLoopPolicy):
   def new_event_loop(self):
      selector = selectors.SelectSelector()
      return asyncio.SelectorEventLoop(selector)

asyncio.set_event_loop_policy(MyPolicy())

Доступность: Unix, Windows.

class asyncio.ProactorEventLoop

Цикл событий для Windows, использующий «порты завершения ввода-вывода» (IOCP).

Доступность: Windows.

См. также

Документация MSDN о портах завершения ввода-вывода.

class asyncio.AbstractEventLoop

Абстрактный базовый класс для циклов событий, совместимых с asyncio.

В разделе Методы цикла событий перечислены все методы, которые должны быть определены в альтернативной реализации AbstractEventLoop.

Примеры

Обратите внимание: во всех примерах этого раздела специально показано использование низкоуровневых API цикла событий, таких как loop.run_forever() и loop.call_soon(). Современные приложения asyncio редко требуется писать таким образом; рассмотрите возможность использования высокоуровневых функций, например asyncio.run().

Hello World с call_soon()

Пример использования метода loop.call_soon() для планирования обратного вызова. Обратный вызов выводит "Hello World", а затем останавливает цикл событий:

import asyncio

def hello_world(loop):
    """A callback to print 'Hello World' and stop the event loop"""
    print('Hello World')
    loop.stop()

loop = asyncio.new_event_loop()

# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)

# Blocking call interrupted by loop.stop()
try:
    loop.run_forever()
finally:
    loop.close()

См. также

Похожий пример Hello World, созданный с помощью корутины и функции run().

Отображение текущей даты с помощью call_later()

Пример обратного вызова, отображающего текущую дату каждую секунду. Обратный вызов использует метод loop.call_later(), чтобы запланировать повторный вызов через 5 секунд, а затем останавливает цикл событий:

import asyncio
import datetime

def display_date(end_time, loop):
    print(datetime.datetime.now())
    if (loop.time() + 1.0) < end_time:
        loop.call_later(1, display_date, end_time, loop)
    else:
        loop.stop()

loop = asyncio.new_event_loop()

# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)

# Blocking call interrupted by loop.stop()
try:
    loop.run_forever()
finally:
    loop.close()

См. также

Похожий пример текущей даты, созданный с помощью корутины и функции run().

Ожидание событий чтения на файловом дескрипторе

Ожидает получения данных файловым дескриптором с помощью метода loop.add_reader(), а затем закрывает цикл событий:

import asyncio
from socket import socketpair

# Create a pair of connected file descriptors
rsock, wsock = socketpair()

loop = asyncio.new_event_loop()

def reader():
    data = rsock.recv(100)
    print("Received:", data.decode())

    # We are done: unregister the file descriptor
    loop.remove_reader(rsock)

    # Stop the event loop
    loop.stop()

# Register the file descriptor for read event
loop.add_reader(rsock, reader)

# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())

try:
    # Run the event loop
    loop.run_forever()
finally:
    # We are done. Close sockets and the event loop.
    rsock.close()
    wsock.close()
    loop.close()

См. также

  • Похожий пример с использованием транспортов, протоколов и метода loop.create_connection().
  • Другой похожий пример с использованием высокоуровневой функции asyncio.open_connection() и потоков.

Установка обработчиков сигналов SIGINT и SIGTERM

(Этот signals пример работает только в Unix.)

Зарегистрируйте обработчики сигналов SIGINT и SIGTERM с помощью метода loop.add_signal_handler():

import asyncio
import functools
import os
import signal

def ask_exit(signame, loop):
    print("got signal %s: exit" % signame)
    loop.stop()

async def main():
    loop = asyncio.get_running_loop()

    for signame in {'SIGINT', 'SIGTERM'}:
        loop.add_signal_handler(
            getattr(signal, signame),
            functools.partial(ask_exit, signame, loop))

    await asyncio.sleep(3600)

print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")

asyncio.run(main())

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/asyncio-eventloop.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API