asyncio-eventloop.md
1> **Источник:** https://python-all.ru/3.16/library/asyncio-eventloop.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Цикл событий89**Исходный код:** [Lib/asyncio/events.py](https://python-all.ru/src/main/Lib/asyncio/events.py), [Lib/asyncio/base\_events.py](https://python-all.ru/src/main/Lib/asyncio/base_events.py)1011---1213Предисловие1415Цикл событий – ядро каждого приложения asyncio. Циклы событий выполняют асинхронные задачи и колбэки, осуществляют сетевые операции ввода-вывода и запускают подпроцессы.1617Разработчикам приложений обычно следует использовать высокоуровневые функции asyncio, такие как [`asyncio.run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run), и редко требуется обращаться к объекту цикла или вызывать его методы. Этот раздел предназначен в основном для авторов низкоуровневого кода, библиотек и фреймворков, которым нужен более тонкий контроль над поведением цикла событий.1819Получение цикла событий2021Следующие низкоуровневые функции можно использовать для получения, установки или создания цикла событий:2223#### `asyncio.get_running_loop()`2425Возвращает работающий цикл событий в текущем потоке ОС.2627Возбуждает [`RuntimeError`](https://python-all.ru/3.16/library/exceptions.html#RuntimeError), если нет работающего цикла событий.2829Эту функцию можно вызывать только из корутины или колбэка.3031Добавлено в версии 3.7.3233#### `asyncio.get_event_loop()`3435Получает текущий цикл событий.3637При вызове из корутины или колбэка (например, запланированного с помощью call\_soon или аналогичного API), эта функция всегда возвращает работающий цикл событий.3839Если работающий цикл событий не установлен, функция вернёт цикл, установленный с помощью [`set_event_loop()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.set_event_loop), или возбудит [`RuntimeError`](https://python-all.ru/3.16/library/exceptions.html#RuntimeError), если цикл не был установлен.4041Поскольку поведение этой функции довольно сложное, использование функции [`get_running_loop()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.get_running_loop) предпочтительнее, чем `get_event_loop()` в корутинах и колбэках.4243Как отмечено выше, рассмотрите использование высокоуровневой функции [`asyncio.run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run) вместо использования этих низкоуровневых функций для ручного создания и закрытия цикла событий.4445Изменено в версии 3.14: Возбуждает [`RuntimeError`](https://python-all.ru/3.16/library/exceptions.html#RuntimeError), если нет текущего цикла событий.4647#### `asyncio.set_event_loop(loop)`4849Устанавливает *loop* в качестве текущего цикла событий для текущего потока ОС.5051#### `asyncio.new_event_loop()`5253Создаёт и возвращает новый объект цикла событий.5455Содержание5657Эта страница документации содержит следующие разделы:5859- Раздел [Методы цикла событий](https://python-all.ru/3.16/library/asyncio-eventloop.html#event-loop-methods) – это справочная документация по API цикла событий;60- Раздел [Обработчики колбэков](https://python-all.ru/3.16/library/asyncio-eventloop.html#callback-handles) документирует экземпляры [`Handle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Handle) и [`TimerHandle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.TimerHandle), которые возвращаются из методов планирования, таких как [`loop.call_soon()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon) и [`loop.call_later()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_later);61- Раздел [Объекты сервера](https://python-all.ru/3.16/library/asyncio-eventloop.html#server-objects) документирует типы, возвращаемые методами цикла событий, такими как [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server);62- Раздел [Реализации цикла событий](https://python-all.ru/3.16/library/asyncio-eventloop.html#event-loop-implementations) документирует классы [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) и [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop);63- Раздел [Примеры](https://python-all.ru/3.16/library/asyncio-eventloop.html#examples) показывает, как работать с некоторыми API цикла событий.6465## Методы цикла событий6667Циклы событий имеют **низкоуровневые** API для следующего:6869[Запуск и остановка цикла событий](https://python-all.ru/3.16/library/asyncio-eventloop.html#running-and-stopping-the-loop) [Планирование колбэков](https://python-all.ru/3.16/library/asyncio-eventloop.html#scheduling-callbacks) [Планирование отложенных колбэков](https://python-all.ru/3.16/library/asyncio-eventloop.html#scheduling-delayed-callbacks) [Создание future и задач](https://python-all.ru/3.16/library/asyncio-eventloop.html#creating-futures-and-tasks) [Открытие сетевых соединений](https://python-all.ru/3.16/library/asyncio-eventloop.html#opening-network-connections) [Создание сетевых серверов](https://python-all.ru/3.16/library/asyncio-eventloop.html#creating-network-servers) [Передача файлов](https://python-all.ru/3.16/library/asyncio-eventloop.html#transferring-files) [Обновление TLS](https://python-all.ru/3.16/library/asyncio-eventloop.html#tls-upgrade) [Наблюдение за файловыми дескрипторами](https://python-all.ru/3.16/library/asyncio-eventloop.html#watching-file-descriptors) [Работа с объектами сокетов напрямую](https://python-all.ru/3.16/library/asyncio-eventloop.html#working-with-socket-objects-directly) [DNS](https://python-all.ru/3.16/library/asyncio-eventloop.html#dns) [Работа с каналами](https://python-all.ru/3.16/library/asyncio-eventloop.html#working-with-pipes) [Сигналы Unix](https://python-all.ru/3.16/library/asyncio-eventloop.html#unix-signals) [Выполнение кода в пулах потоков или процессов](https://python-all.ru/3.16/library/asyncio-eventloop.html#executing-code-in-thread-or-process-pools) [API обработки ошибок](https://python-all.ru/3.16/library/asyncio-eventloop.html#error-handling-api) [Включение режима отладки](https://python-all.ru/3.16/library/asyncio-eventloop.html#enabling-debug-mode) [Запуск подпроцессов](https://python-all.ru/3.16/library/asyncio-eventloop.html#running-subprocesses)7071### [Запуск и остановка цикла](https://python-all.ru/3.16/library/asyncio-eventloop.html#id1)7273#### `loop.run_until_complete(future)`7475Выполняется до тех пор, пока *future* (экземпляр [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future)) не завершится.7677Если аргумент является [объектом корутины](https://python-all.ru/3.16/library/asyncio-task.html#coroutine), он неявно планируется для выполнения как [`asyncio.Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task).7879Возвращает результат Future или возбуждает его исключение.8081#### `loop.run_forever()`8283Запускает цикл событий до вызова [`stop()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.stop).8485Если [`stop()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.stop) вызывается до вызова `run_forever()`, цикл один раз опросит I/O-селектор с нулевым таймаутом, выполнит все колбэки, запланированные в ответ на события ввода-вывода (и уже запланированные), а затем завершится.8687Если [`stop()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.stop) вызывается во время выполнения `run_forever()`, цикл выполнит текущий пакет колбэков и завершится. Обратите внимание: новые колбэки, запланированные другими колбэками, в этом случае не запустятся; вместо этого они будут выполнены при следующем вызове `run_forever()` или [`run_until_complete()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.run_until_complete).8889#### `loop.stop()`9091Останавливает цикл событий.9293#### `loop.is_running()`9495Возвращает `True`, если цикл событий в данный момент выполняется.9697#### `loop.is_closed()`9899Возвращает `True`, если цикл событий был закрыт.100101#### `loop.close()`102103Закрывает цикл событий.104105Цикл не должен выполняться при вызове этой функции. Все ожидающие колбэки будут отброшены.106107Этот метод очищает все очереди и завершает работу исполнителя, но не ожидает завершения исполнителя.108109Этот метод идемпотентен и необратим. После закрытия цикла событий не следует вызывать другие методы.110111#### `async loop.shutdown_asyncgens()`112113Планирует закрытие всех открытых [асинхронных генераторов](https://python-all.ru/3.16/glossary.html#term-asynchronous-generator) с помощью вызова [`aclose()`](https://python-all.ru/3.16/reference/expressions.html#agen.aclose). После вызова этого метода цикл событий будет выдавать предупреждение, если выполняется итерация нового асинхронного генератора. Это следует использовать для надёжного завершения всех запланированных асинхронных генераторов.114115Обратите внимание: вызывать эту функцию не нужно, если используется [`asyncio.run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run).116117Пример:118119```python120try:121 loop.run_forever()122finally:123 loop.run_until_complete(loop.shutdown_asyncgens())124 loop.close()125```126127Добавлено в версии 3.6.128129#### `async loop.shutdown_default_executor(timeout=None)`130131Планирует закрытие исполнителя по умолчанию и ожидает завершения всех потоков в [`ThreadPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor). Как только этот метод будет вызван, использование исполнителя по умолчанию с [`loop.run_in_executor()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.run_in_executor) приведёт к возникновению [`RuntimeError`](https://python-all.ru/3.16/library/exceptions.html#RuntimeError).132133Параметр *timeout* задаёт количество времени (в [`float`](https://python-all.ru/3.16/library/functions.html#float) секундах), которое даётся исполнителю на завершение присоединения потоков. По умолчанию `None` исполнителю выделяется неограниченное время.134135Если *timeout* истекает, генерируется [`RuntimeWarning`](https://python-all.ru/3.16/library/exceptions.html#RuntimeWarning) и исполнитель по умолчанию завершается без ожидания завершения присоединения своих потоков.136137> **Примечание**138>139> Не следует вызывать этот метод при использовании [`asyncio.run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run), так как последний обрабатывает завершение исполнителя по умолчанию автоматически.140141Добавлено в версии 3.9.142143Изменено в версии 3.12: Добавлен параметр *timeout*.144145### [Планирование колбэков](https://python-all.ru/3.16/library/asyncio-eventloop.html#id2)146147#### `loop.call_soon(callback, *args, context=None)`148149Планирует вызов *колбэк* [колбэк](https://python-all.ru/3.16/glossary.html#term-callback) с аргументами *args* на следующей итерации цикла событий.150151Возвращает экземпляр [`asyncio.Handle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Handle), который можно использовать для отмены колбэка.152153Колбэки вызываются в порядке их регистрации. Каждый колбэк будет вызван ровно один раз.154155Необязательный аргумент *context* (только ключевое слово) задаёт пользовательский [`contextvars.Context`](https://python-all.ru/3.16/library/contextvars.html#contextvars.Context) для выполнения *колбэк*. Если *context* не указан, используется текущий контекст.156157В отличие от [`call_soon_threadsafe()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe), этот метод не является потокобезопасным.158159#### `loop.call_soon_threadsafe(callback, *args, context=None)`160161Потокобезопасный вариант [`call_soon()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon). При планировании колбэков из другого потока *обязательно* использовать эту функцию, так как `call_soon()` не является потокобезопасным.162163Эту функцию можно безопасно вызывать из реентерабельного контекста или обработчика сигналов, однако использование возвращаемого дескриптора в таких контекстах небезопасно и не имеет смысла.164165Возбуждает [`RuntimeError`](https://python-all.ru/3.16/library/exceptions.html#RuntimeError), если вызван на закрытом цикле событий. Это может произойти во вторичном потоке при завершении главного приложения.166167См. раздел [concurrency and multithreading](https://python-all.ru/3.16/library/asyncio-dev.html#asyncio-multithreading) документации.168169Изменено в версии 3.7: Добавлен параметр *context* (только ключевое слово). Подробнее см. [**PEP 567**](https://python-all.ru/3.16/library/asyncio-eventloop.html).170171> **Примечание**172>173> Большинство функций планирования [`asyncio`](https://python-all.ru/3.16/library/asyncio.html#module-asyncio) не позволяют передавать именованные аргументы. Для этого используйте [`functools.partial()`](https://python-all.ru/3.16/library/functools.html#functools.partial):174>175> ```python176> # запланирует "print("Hello", flush=True)"177> loop.call_soon(178> functools.partial(print, "Hello", flush=True))179> ```180>181> Использование partial-объектов обычно удобнее лямбд, так как asyncio может лучше отображать partial-объекты в сообщениях отладки и ошибок.182183### [Планирование отложенных колбэков](https://python-all.ru/3.16/library/asyncio-eventloop.html#id3)184185Цикл событий предоставляет механизмы для планирования вызова функций-колбэков в некоторый момент в будущем. Цикл событий использует монотонные часы для отслеживания времени.186187#### `loop.call_later(delay, callback, *args, context=None)`188189Планирует вызов *колбэк* через заданное количество секунд *delay* (может быть целым числом или числом с плавающей запятой).190191Возвращается экземпляр [`asyncio.TimerHandle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.TimerHandle), который можно использовать для отмены колбэка.192193*колбэк* будет вызван ровно один раз. Если два колбэка запланированы на одно и то же время, порядок их вызова не определён.194195Необязательные позиционные аргументы *args* будут переданы колбэку при его вызове. Используйте [`functools.partial()`](https://python-all.ru/3.16/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio-pass-keywords) в *колбэк*.196197Необязательный аргумент *context* (только ключевое слово) позволяет задать пользовательский [`contextvars.Context`](https://python-all.ru/3.16/library/contextvars.html#contextvars.Context) для выполнения *колбэк*. Если *context* не указан, используется текущий контекст.198199> **Примечание**200>201> В целях производительности колбэки, запланированные с помощью `loop.call_later()`, могут выполняться с опережением до одного такта системных часов (см. `time.get_clock_info('monotonic').resolution`).202203Изменено в версии 3.7: Добавлен параметр *context* (только ключевое слово). Подробнее см. [**PEP 567**](https://python-all.ru/3.16/library/asyncio-eventloop.html).204205Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией цикла событий по умолчанию параметр *delay* не мог превышать одного дня. В Python 3.8 это исправлено.206207#### `loop.call_at(when, callback, *args, context=None)`208209Планирует вызов *колбэк* в заданную абсолютную временную метку *when* (целое число или число с плавающей запятой), используя ту же временную шкалу, что и [`loop.time()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.time).210211Поведение этого метода аналогично [`call_later()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_later).212213Возвращается экземпляр [`asyncio.TimerHandle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.TimerHandle), который можно использовать для отмены колбэка.214215> **Примечание**216>217> В целях производительности колбэки, запланированные с помощью `loop.call_at()`, могут выполняться с опережением до одного такта системных часов (см. `time.get_clock_info('monotonic').resolution`).218219Изменено в версии 3.7: Добавлен параметр *context* (только ключевое слово). Подробнее см. [**PEP 567**](https://python-all.ru/3.16/library/asyncio-eventloop.html).220221Изменено в версии 3.8: В Python 3.7 и более ранних версиях с реализацией цикла событий по умолчанию разность между *when* и текущим временем не могла превышать одного дня. В Python 3.8 это исправлено.222223#### `loop.time()`224225Возвращает текущее время, как значение [`float`](https://python-all.ru/3.16/library/functions.html#float), в соответствии с внутренними монотонными часами цикла событий.226227> **Примечание**228>229> Изменено в версии 3.8: В Python 3.7 и более ранних версиях таймауты (относительная *задержка* или абсолютное значение *when*) не должны были превышать одного дня. Это было исправлено в Python 3.8.230231> **См. также**232>233> Функция [`asyncio.sleep()`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.sleep).234235### [Создание futures и задач](https://python-all.ru/3.16/library/asyncio-eventloop.html#id4)236237#### `loop.create_future()`238239Создаёт объект [`asyncio.Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future), привязанный к циклу событий.240241Это предпочтительный способ создания Future в asyncio. Он позволяет сторонним циклам событий предоставлять альтернативные реализации объекта Future (с лучшей производительностью или инструментарием).242243Добавлено в версии 3.5.2.244245#### `loop.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)`246247Планирует выполнение [корутины](https://python-all.ru/3.16/library/asyncio-task.html#coroutine) *coro*. Возвращает объект [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task).248249Сторонние циклы событий могут использовать свой собственный подкласс [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) для совместимости. В этом случае тип результата является подклассом `Task`.250251Полная сигнатура функции в основном такая же, как у конструктора (или фабрики) [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) – все именованные аргументы этой функции передаются в этот интерфейс.252253Если аргумент *name* указан и не равен `None`, он устанавливается как имя задачи с помощью [`Task.set_name()`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task.set_name).254255Необязательный именованный аргумент *context* позволяет указать пользовательский [`contextvars.Context`](https://python-all.ru/3.16/library/contextvars.html#contextvars.Context) для выполнения *coro*. Копия текущего контекста создаётся, если *context* не передан.256257Необязательный именованный аргумент *eager\_start* позволяет указать, должна ли задача выполняться немедленно при вызове create\_task или быть запланирована позднее. Если *eager\_start* не передан, используется режим, установленный с помощью [`loop.set_task_factory()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.set_task_factory).258259Изменено в версии 3.8: Добавлен параметр *name*.260261Изменено в версии 3.11: Добавлен параметр *context*.262263Изменено в версии 3.13.3: Добавлен `kwargs`, который передаёт произвольные дополнительные параметры, включая `name` и `context`.264265Изменено в версии 3.13.4: Отменено изменение, передававшее *name* и *context* (если они равны None), при этом другие произвольные именованные аргументы всё ещё передаются (чтобы избежать нарушения обратной совместимости с 3.13.3).266267Изменено в версии 3.14: Теперь передаются все *kwargs*. Параметр *eager\_start* работает с eager-фабриками задач.268269#### `loop.set_task_factory(factory)`270271Устанавливает фабрику задач, которая будет использоваться [`loop.create_task()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_task).272273Если *factory* равно `None`, будет установлена фабрика задач по умолчанию. В противном случае *factory* должна быть *вызываемой* с сигнатурой, соответствующей `(loop, coro, **kwargs)`, где *loop* – ссылка на активный цикл событий, а *coro* – объект корутины. Вызываемая сущность должна передавать все *kwargs* и возвращать объект, совместимый с [`asyncio.Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task).274275Изменено в версии 3.13.3: Требуется, чтобы все *kwargs* передавались в [`asyncio.Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task).276277Изменено в версии 3.13.4: *name* больше не передаётся в фабрики задач. *context* больше не передаётся в фабрики задач, если он равен `None`.278279Изменено в версии 3.14: *name* и *context* теперь снова безусловно передаются в фабрики задач.280281#### `loop.get_task_factory()`282283Возвращает фабрику задач или `None`, если используется стандартная.284285### [Открытие сетевых соединений](https://python-all.ru/3.16/library/asyncio-eventloop.html#id5)286287#### `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)`288289Открывает потоковое транспортное соединение по заданному адресу, указанному в *host* и *port*.290291Семейство сокетов может быть [`AF_INET`](https://python-all.ru/3.16/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.16/library/socket.html#socket.AF_INET6) в зависимости от *host* (или аргумента *family*, если он передан).292293Тип сокета будет [`SOCK_STREAM`](https://python-all.ru/3.16/library/socket.html#socket.SOCK_STREAM).294295*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола asyncio](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).296297Этот метод попытается установить соединение в фоновом режиме. При успехе он возвращает пару `(transport, protocol)`.298299Хронологическая последовательность выполняемой операции следующая:3003011. Соединение устанавливается, и для него создаётся [транспорт](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-transport) .3022. *protocol\_factory* вызывается без аргументов и должен вернуть экземпляр [протокола](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).3033. Экземпляр протокола связывается с транспортом вызовом его метода [`connection_made()`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.BaseProtocol.connection_made).3044. При успехе возвращается кортеж `(transport, protocol)`.305306Созданный транспорт представляет собой двунаправленный поток данных, зависящий от реализации.307308Другие аргументы:309310- *ssl*: если указан и не равен false, создаётся транспорт SSL/TLS (по умолчанию создаётся обычный TCP-транспорт). Если *ssl* является объектом [`ssl.SSLContext`](https://python-all.ru/3.16/library/ssl.html#ssl.SSLContext), этот контекст используется для создания транспорта; если *ssl* равно [`True`](https://python-all.ru/3.16/library/constants.html#True), используется контекст по умолчанию, возвращаемый из [`ssl.create_default_context()`](https://python-all.ru/3.16/library/ssl.html#ssl.create_default_context).311312 > **См. также**313 >314 > [Вопросы безопасности SSL/TLS](https://python-all.ru/3.16/library/ssl.html#ssl-security)315- *server\_hostname* задаёт или переопределяет имя хоста, с которым будет сверяться сертификат целевого сервера. Следует передавать только если *ssl* не равен `None`. По умолчанию используется значение аргумента *host*. Если *host* пуст, значения по умолчанию нет, и необходимо передать значение для *server\_hostname*. Если *server\_hostname* – пустая строка, сопоставление имён хостов отключается (что представляет серьёзную угрозу безопасности, допуская атаки «человек посередине»).316- *family*, *proto*, *flags* – необязательные семейство адресов, протокол и флаги, которые передаются в getaddrinfo() для разрешения *host*. Если заданы, все они должны быть целыми числами из соответствующих констант модуля [`socket`](https://python-all.ru/3.16/library/socket.html#module-socket).317- *happy\_eyeballs\_delay*, если задан, включает Happy Eyeballs для этого соединения. Должен быть числом с плавающей запятой, представляющим время в секундах ожидания завершения попытки соединения перед запуском следующей параллельной попытки. Это «задержка попытки соединения», как определено в [**RFC 8305**](https://python-all.ru/3.16/library/asyncio-eventloop.html). Разумное значение по умолчанию, рекомендуемое RFC, – `0.25` (250 миллисекунд).318- *interleave* управляет переупорядочением адресов, когда имя хоста разрешается в несколько IP-адресов. Если `0` или не указан, переупорядочение не выполняется, и адреса перебираются в порядке, возвращаемом [`getaddrinfo()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo). Если указано положительное целое число, адреса перемежаются по семейству адресов, и заданное число интерпретируется как «количество первого семейства адресов», как определено в [**RFC 8305**](https://python-all.ru/3.16/library/asyncio-eventloop.html). Значение по умолчанию – `0`, если *happy\_eyeballs\_delay* не указан, и `1`, если указан.319- *sock*, если задан, должен быть существующим, уже подключённым объектом [`socket.socket`](https://python-all.ru/3.16/library/socket.html#socket.socket), который будет использоваться транспортом. Если задан *sock*, не должны указываться ни *host*, *port*, *family*, *proto*, *flags*, *happy\_eyeballs\_delay*, *interleave*, ни *local\_addr*.320321 > **Примечание**322 >323 > Аргумент *sock* передаёт право владения сокетом созданному транспорту. Чтобы закрыть сокет, вызовите метод транспорта [`close()`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.BaseTransport.close).324- *local\_addr*, если задан, представляет собой кортеж `(local_host, local_port)`, используемый для локальной привязки сокета. *local\_host* и *local\_port* разрешаются с помощью `getaddrinfo()`, аналогично *host* и *port*.325- *ssl\_handshake\_timeout* (для TLS-соединения) – время в секундах ожидания завершения рукопожатия TLS перед разрывом соединения. `60.0` секунд, если `None` (по умолчанию).326- *ssl\_shutdown\_timeout* – время в секундах ожидания завершения завершения SSL перед разрывом соединения. `30.0` секунд, если `None` (по умолчанию).327- *all\_errors* определяет, какие исключения возбуждаются, когда соединение не может быть создано. По умолчанию возбуждается только одно `Exception`: первое исключение, если оно одно или все ошибки имеют одинаковое сообщение, или одно `OSError` с объединёнными сообщениями об ошибках. Когда `all_errors` равно `True`, возбуждается `ExceptionGroup`, содержащее все исключения (даже если оно единственное).328329Изменено в версии 3.5: Добавлена поддержка SSL/TLS в [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).330331Изменено в версии 3.6: Параметр сокета [socket.TCP\_NODELAY](https://python-all.ru/3.16/library/socket.html#socket-unix-constants) теперь устанавливается по умолчанию для всех TCP-соединений.332333Изменено в версии 3.7: Добавлен параметр *ssl\_handshake\_timeout*.334335Изменено в версии 3.8: Добавлены параметры *happy\_eyeballs\_delay* и *interleave*.336337Алгоритм Happy Eyeballs: успех с двухстековыми хостами. Когда IPv4-путь и протокол сервера работают, а IPv6-путь и протокол сервера не работают, двухстековое клиентское приложение испытывает значительную задержку соединения по сравнению с клиентом, использующим только IPv4. Это нежелательно, так как ухудшает пользовательский опыт для двухстекового клиента. В этом документе указаны требования к алгоритмам, уменьшающим эту заметную пользователю задержку, и приводится сам алгоритм.338339Дополнительная информация: [https://datatracker.ietf.org/doc/html/rfc6555](https://python-all.ru/3.16/library/asyncio-eventloop.html)340341Изменено в версии 3.11: Добавлен параметр *ssl\_shutdown\_timeout*.342343Изменено в версии 3.12: Добавлен параметр *all\_errors*.344345> **См. также**346>347> Функция [`open_connection()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.open_connection) является высокоуровневой альтернативой API. Она возвращает пару ([`StreamReader`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.StreamReader), [`StreamWriter`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.StreamWriter)), которую можно использовать непосредственно в коде с async/await.348349#### `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)`350351Создать датаграммное соединение.352353Семейство сокетов может быть одним из [`AF_INET`](https://python-all.ru/3.16/library/socket.html#socket.AF_INET), [`AF_INET6`](https://python-all.ru/3.16/library/socket.html#socket.AF_INET6) или [`AF_UNIX`](https://python-all.ru/3.16/library/socket.html#socket.AF_UNIX), в зависимости от *host* (или аргумента *family*, если он задан).354355Тип сокета будет [`SOCK_DGRAM`](https://python-all.ru/3.16/library/socket.html#socket.SOCK_DGRAM).356357*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокол](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).358359При успехе возвращается кортеж из `(transport, protocol)`.360361Остальные аргументы:362363- *local\_addr*, если задан, представляет собой кортеж `(local_host, local_port)`, используемый для локальной привязки сокета. *local\_host* и *local\_port* разрешаются с помощью [`getaddrinfo()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo).364365 > **Примечание**366 >367 > В Windows при использовании цикла событий proactor с `local_addr=None` будет возбуждено [`OSError`](https://python-all.ru/3.16/library/exceptions.html#OSError) с `errno.WSAEINVAL` при его запуске.368- *remote\_addr*, если задан, представляет собой кортеж `(remote_host, remote_port)`, используемый для подключения сокета к удалённому адресу. *remote\_host* и *remote\_port* разрешаются с помощью [`getaddrinfo()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo).369- *family*, *proto*, *flags* – необязательные семейство адресов, протокол и флаги, передаваемые в [`getaddrinfo()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo) для разрешения *host*. Если заданы, все они должны быть целыми числами из соответствующих констант модуля [`socket`](https://python-all.ru/3.16/library/socket.html#module-socket).370- *reuse\_port* указывает ядру разрешить привязку данной конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Этот параметр не поддерживается в Windows и некоторых Unix-системах. Если константа [socket.SO\_REUSEPORT](https://python-all.ru/3.16/library/socket.html#socket-unix-constants) не определена, то эта возможность не поддерживается.371- *allow\_broadcast* указывает ядру разрешить этой конечной точке отправлять сообщения на широковещательный адрес.372- *sock* может быть указан необязательно, чтобы использовать уже существующий, подключённый объект [`socket.socket`](https://python-all.ru/3.16/library/socket.html#socket.socket) для транспорта. Если указан, *local\_addr* и *remote\_addr* должны быть опущены (должны быть [`None`](https://python-all.ru/3.16/library/constants.html#None)).373374 > **Примечание**375 >376 > Аргумент *sock* передаёт владение сокетом созданному транспорту. Чтобы закрыть сокет, вызовите метод [`close()`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.BaseTransport.close) транспорта.377378См. примеры [протокол UDP-клиента эхо](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-udp-echo-client-protocol) и [протокол UDP-сервера эхо](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-udp-echo-server-protocol).379380Изменено в версии 3.4.4: Добавлены параметры *family*, *proto*, *flags*, *reuse\_address*, *reuse\_port*, *allow\_broadcast* и *sock*.381382Изменено в версии 3.8: Добавлена поддержка Windows.383384Изменено в версии 3.8.1: Параметр *reuse\_address* больше не поддерживается, поскольку использование [socket.SO\_REUSEADDR](https://python-all.ru/3.16/library/socket.html#socket-unix-constants) представляет существенную угрозу безопасности для UDP. Явная передача `reuse_address=True` приведёт к возбуждению исключения.385386Когда несколько процессов с разными UID назначают сокеты одному и тому же адресу UDP-сокета с помощью `SO_REUSEADDR`, входящие пакеты могут случайным образом распределяться между сокетами.387388На поддерживаемых платформах *reuse\_port* может использоваться как замена аналогичной функциональности. При *reuse\_port* вместо этого применяется [socket.SO\_REUSEPORT](https://python-all.ru/3.16/library/socket.html#socket-unix-constants), который специально предотвращает назначение сокетов одному и тому же адресу сокета процессами с разными UID.389390Изменено в версии 3.11: Параметр *reuse\_address*, отключённый начиная с Python 3.8.1, 3.7.6 и 3.6.10, был полностью удалён.391392#### `async loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)`393394Создать Unix-соединение.395396Семейство сокетов будет [`AF_UNIX`](https://python-all.ru/3.16/library/socket.html#socket.AF_UNIX); тип сокета будет [`SOCK_STREAM`](https://python-all.ru/3.16/library/socket.html#socket.SOCK_STREAM).397398При успехе возвращается кортеж из `(transport, protocol)`.399400*path* – это имя доменного сокета Unix, обязательный параметр, если не указан параметр *sock*. Поддерживаются абстрактные сокеты Unix, пути [`str`](https://python-all.ru/3.16/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.16/library/stdtypes.html#bytes) и [`Path`](https://python-all.ru/3.16/library/pathlib.html#pathlib.Path).401402См. документацию метода [`loop.create_connection()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_connection) для получения информации об аргументах этого метода.403404[Availability](https://python-all.ru/3.16/library/intro.html#availability): Unix.405406Изменено в версии 3.7: Добавлен параметр *ssl\_handshake\_timeout*. Параметр *path* теперь может быть [объектом, подобным пути](https://python-all.ru/3.16/glossary.html#term-path-like-object).407408Изменено в версии 3.11: Добавлен параметр *ssl\_shutdown\_timeout*.409410### [Создание сетевых серверов](https://python-all.ru/3.16/library/asyncio-eventloop.html#id6)411412#### `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, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)`413414Создаёт TCP-сервер (тип сокета [`SOCK_STREAM`](https://python-all.ru/3.16/library/socket.html#socket.SOCK_STREAM)), прослушивающий порт на адресе *хоста*.415416Возвращает объект [`Server`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server).417418Аргументы:419420- *protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).421- Параметр *host* может принимать значения нескольких типов, которые определяют, где будет слушать сервер:422423 - Если *host* – строка, TCP-сервер привязывается к одному сетевому интерфейсу, указанному в *host*.424 - Если *host* – последовательность строк, TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в этой последовательности.425 - Если *host* – пустая строка или `None`, подразумеваются все интерфейсы, и будет возвращён список из нескольких сокетов (скорее всего, один для IPv4 и один для IPv6).426- Параметр *port* можно задать, чтобы указать, какой порт должен слушать сервер. Если `0` или `None` (по умолчанию), будет выбран случайный свободный порт (обратите внимание: если *host* разрешается в несколько сетевых интерфейсов, для каждого интерфейса будет выбран разный случайный порт).427- *family* может быть установлен в [`socket.AF_INET`](https://python-all.ru/3.16/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.16/library/socket.html#socket.AF_INET6), чтобы принудительно использовать IPv4 или IPv6. Если не задан, *family* будет определён по имени хоста (по умолчанию [`AF_UNSPEC`](https://python-all.ru/3.16/library/socket.html#socket.AF_UNSPEC)).428- *flags* – битовая маска для [`getaddrinfo()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo).429- *sock* может быть указан опционально, чтобы использовать уже существующий объект сокета. Если он указан, *host* и *port* не должны быть заданы.430431 > **Примечание**432 >433 > Аргумент *sock* передаёт владение сокетом созданному серверу. Чтобы закрыть сокет, вызовите метод сервера [`close()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.close).434- *backlog* – максимальное количество соединений в очереди, передаваемое в [`listen()`](https://python-all.ru/3.16/library/socket.html#socket.socket.listen) (по умолчанию 100).435- *ssl* может быть установлен в экземпляр [`SSLContext`](https://python-all.ru/3.16/library/ssl.html#ssl.SSLContext) для включения TLS для принимаемых соединений.436- *reuse\_address* указывает ядру повторно использовать локальный сокет в состоянии `TIME_WAIT`, не дожидаясь истечения его естественного тайм-аута. Если не указан, автоматически устанавливается в `True` на Unix.437- *reuse\_port* указывает ядру разрешить привязку этой конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows.438- *keep\_alive*, установленный в `True`, поддерживает соединения активными, включая периодическую передачу сообщений.439440Изменено в версии 3.13: Добавлен параметр *keep\_alive*.441442- *ssl\_handshake\_timeout* (для TLS-сервера) – время ожидания в секундах завершения TLS-рукопожатия перед разрывом соединения. `60.0` секунд, если `None` (по умолчанию).443- *ssl\_shutdown\_timeout* – время ожидания в секундах завершения SSL shutdown перед разрывом соединения. `30.0` секунд, если `None` (по умолчанию).444- *start\_serving*, установленный в `True` (по умолчанию), заставляет созданный сервер немедленно начать принимать соединения. Если установлен в `False`, пользователь должен дождаться [`Server.start_serving()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.start_serving) или [`Server.serve_forever()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.serve_forever), чтобы сервер начал принимать соединения.445446Изменено в версии 3.5: Добавлена поддержка SSL/TLS в [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).447448Изменено в версии 3.5.1: Параметр *host* может быть последовательностью строк.449450Изменено в версии 3.6: Добавлены параметры *ssl\_handshake\_timeout* и *start\_serving*. Опция сокета [socket.TCP\_NODELAY](https://python-all.ru/3.16/library/socket.html#socket-unix-constants) по умолчанию установлена для всех TCP-соединений.451452Изменено в версии 3.11: Добавлен параметр *ssl\_shutdown\_timeout*.453454> **См. также**455>456> Функция [`start_server()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.start_server) – это API более высокого уровня, который возвращает пару [`StreamReader`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.StreamReader) и [`StreamWriter`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.StreamWriter), которые можно использовать в коде с async/await.457458#### `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, cleanup_socket=True)`459460Аналогично [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server), но работает с семейством сокетов [`AF_UNIX`](https://python-all.ru/3.16/library/socket.html#socket.AF_UNIX).461462*path* – имя сокета домена Unix и является обязательным, если не передан аргумент *sock*. Поддерживаются абстрактные сокеты Unix, пути [`str`](https://python-all.ru/3.16/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.16/library/stdtypes.html#bytes) и [`Path`](https://python-all.ru/3.16/library/pathlib.html#pathlib.Path).463464Если *cleanup\_socket* равен true, то сокет Unix будет автоматически удалён из файловой системы при закрытии сервера, если только сокет не был заменён после создания сервера.465466Информацию об аргументах этого метода см. в документации метода [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server).467468[Доступность](https://python-all.ru/3.16/library/intro.html#availability): Unix.469470Изменено в версии 3.7: Добавлены параметры *ssl\_handshake\_timeout* и *start\_serving*. Параметр *path* теперь может быть объектом [`Path`](https://python-all.ru/3.16/library/pathlib.html#pathlib.Path).471472Изменено в версии 3.11: Добавлен параметр *ssl\_shutdown\_timeout*.473474Изменено в версии 3.13: Добавлен параметр *cleanup\_socket*.475476#### `async loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)`477478Оборачивает уже принятое соединение в пару транспорт/протокол.479480Этот метод могут использовать серверы, которые принимают соединения вне asyncio, но используют asyncio для их обработки.481482Параметры:483484- *protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).485- *sock* – это существующий объект сокета, возвращённый из [`socket.accept`](https://python-all.ru/3.16/library/socket.html#socket.socket.accept).486487 > **Примечание**488 >489 > Аргумент *sock* передаёт владение сокетом созданному транспорту. Чтобы закрыть сокет, вызовите метод [`close()`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.BaseTransport.close) транспорта.490- *ssl* можно установить в [`SSLContext`](https://python-all.ru/3.16/library/ssl.html#ssl.SSLContext), чтобы включить SSL для принятых соединений.491- *ssl\_handshake\_timeout* (для SSL-соединения) – время в секундах ожидания завершения SSL-рукопожатия перед разрывом соединения. `60.0` секунд, если `None` (по умолчанию).492- *ssl\_shutdown\_timeout* – время в секундах ожидания завершения SSL-завершения перед разрывом соединения. `30.0` секунд, если `None` (по умолчанию).493494Возвращает пару `(transport, protocol)`.495496Добавлено в версии 3.5.3.497498Изменено в версии 3.7: Добавлен параметр *ssl\_handshake\_timeout*.499500Изменено в версии 3.11: Добавлен параметр *ssl\_shutdown\_timeout*.501502### [Передача файлов](https://python-all.ru/3.16/library/asyncio-eventloop.html#id7)503504#### `async loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)`505506Отправляет *файл* через *транспорт*. Возвращает общее количество отправленных байтов.507508Метод использует высокопроизводительный [`os.sendfile()`](https://python-all.ru/3.16/library/os.html#os.sendfile), если доступен.509510*file* должен быть обычным файловым объектом, открытым в бинарном режиме.511512*offset* указывает, откуда начинать чтение файла. Если указан, *count* – общее количество байтов для передачи, в отличие от отправки файла до достижения EOF. Позиция файла всегда обновляется, даже если этот метод вызывает ошибку, и [`file.tell()`](https://python-all.ru/3.16/library/io.html#io.IOBase.tell) можно использовать для получения фактического количества отправленных байтов.513514*fallback*, установленный в `True`, заставляет asyncio вручную читать и отправлять файл, если платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет в Unix).515516Вызывает [`SendfileNotAvailableError`](https://python-all.ru/3.16/library/asyncio-exceptions.html#asyncio.SendfileNotAvailableError), если система не поддерживает системный вызов *sendfile*, а *fallback* равен `False`.517518Добавлено в версии 3.7.519520### [Обновление TLS](https://python-all.ru/3.16/library/asyncio-eventloop.html#id8)521522#### `async loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)`523524Обновляет существующее соединение на основе транспорта до TLS.525526Создаёт экземпляр кодировщика/декодировщика TLS и вставляет его между *транспортом* и *протоколом*. Кодировщик/декодировщик реализует как протокол, обращённый к *транспорту*, так и транспорт, обращённый к *протоколу*.527528Возвращает созданный экземпляр с двумя интерфейсами. После *await* *протокол* должен прекратить использовать исходный *транспорт* и общаться только с возвращённым объектом, поскольку кодировщик кэширует данные со стороны *протокола* и периодически обменивается дополнительными пакетами сеанса TLS с *транспортом*.529530В некоторых ситуациях (например, когда переданный транспорт уже закрывается) это может вернуть `None`.531532Параметры:533534- *транспорт* и *протокол* – экземпляры, возвращаемые методами наподобие [`create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server) и [`create_connection()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_connection).535- *sslcontext*: настроенный экземпляр [`SSLContext`](https://python-all.ru/3.16/library/ssl.html#ssl.SSLContext).536- *server\_side* передавайте `True` при обновлении серверного соединения (например, созданного [`create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server)).537- *server\_hostname*: задаёт или переопределяет имя хоста, с которым будет сверяться сертификат целевого сервера.538- *ssl\_handshake\_timeout* – время в секундах, в течение которого ожидается завершение TLS-рукопожатия перед разрывом соединения (для TLS-соединений). `60.0` секунд, если `None` (по умолчанию).539- *ssl\_shutdown\_timeout* – время в секундах, в течение которого ожидается завершение завершения SSL перед разрывом соединения. `30.0` секунд, если `None` (по умолчанию).540541Добавлено в версии 3.7.542543Изменено в версии 3.11: Добавлен параметр *ssl\_shutdown\_timeout*.544545### [Наблюдение за файловыми дескрипторами](https://python-all.ru/3.16/library/asyncio-eventloop.html#id9)546547#### `loop.add_reader(fd, callback, *args)`548549Начинает наблюдение за файловым дескриптором *fd* на готовность к чтению и вызывает *колбэк* с указанными аргументами, как только *fd* станет доступен для чтения.550551Любой ранее зарегистрированный колбэк для *fd* отменяется и заменяется на *колбэк*.552553#### `loop.remove_reader(fd)`554555Прекращает наблюдение за файловым дескриптором *fd* на готовность к чтению. Возвращает `True`, если *fd* ранее наблюдался на чтение.556557#### `loop.add_writer(fd, callback, *args)`558559Начинает наблюдение за файловым дескриптором *fd* на готовность к записи и вызывает *колбэк* с указанными аргументами *args*, как только *fd* станет доступен для записи.560561Любой ранее зарегистрированный колбэк для *fd* отменяется и заменяется на *колбэк*.562563Используйте [`functools.partial()`](https://python-all.ru/3.16/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio-pass-keywords) в *колбэк*.564565#### `loop.remove_writer(fd)`566567Прекращает наблюдение за файловым дескриптором *fd* на готовность к записи. Возвращает `True`, если *fd* ранее наблюдался на запись.568569См. также раздел [Поддержка платформ](https://python-all.ru/3.16/library/asyncio-platforms.html#asyncio-platform-support) о некоторых ограничениях этих методов.570571### [Работа с объектами сокетов напрямую](https://python-all.ru/3.16/library/asyncio-eventloop.html#id10)572573В целом реализации протоколов, использующие API на основе транспорта, такие как [`loop.create_connection()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_connection) и [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server), работают быстрее реализаций, работающих напрямую с сокетами. Однако есть случаи, когда производительность не критична, и работать напрямую с объектами [`socket`](https://python-all.ru/3.16/library/socket.html#socket.socket) удобнее.574575#### `async loop.sock_recv(sock, nbytes)`576577Получает до *nbytes* байт из *sock*. Асинхронная версия [`socket.recv()`](https://python-all.ru/3.16/library/socket.html#socket.socket.recv).578579Возвращает полученные данные в виде объекта bytes.580581*sock* должен быть неблокирующим сокетом.582583Изменено в версии 3.7: Хотя этот метод всегда документировался как корутинный, до Python 3.7 он возвращал [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7 это `async def` метод.584585#### `async loop.sock_recv_into(sock, buf)`586587Получает данные из *sock* в буфер *buf*. По аналогии с блокирующим методом [`socket.recv_into()`](https://python-all.ru/3.16/library/socket.html#socket.socket.recv_into).588589Возвращает количество байт, записанных в буфер.590591*sock* должен быть неблокирующим сокетом.592593Добавлено в версии 3.7.594595#### `async loop.sock_recvfrom(sock, bufsize)`596597Получает дейтаграмму размером до *bufsize* из *sock*. Асинхронная версия [`socket.recvfrom()`](https://python-all.ru/3.16/library/socket.html#socket.socket.recvfrom).598599Возвращает кортеж (полученные данные, удалённый адрес).600601*sock* должен быть неблокирующим сокетом.602603Добавлено в версии 3.12.604605#### `async loop.sock_recvfrom_into(sock, buf, nbytes=0)`606607Получает дейтаграмму размером до *nbytes* из *sock* в *buf*. Асинхронная версия [`socket.recvfrom_into()`](https://python-all.ru/3.16/library/socket.html#socket.socket.recvfrom_into).608609Возвращает кортеж (количество полученных байт, удалённый адрес).610611*sock* должен быть неблокирующим сокетом.612613Добавлено в версии 3.12.614615#### `async loop.sock_sendall(sock, data)`616617Отправляет *data* в сокет *sock*. Асинхронная версия [`socket.sendall()`](https://python-all.ru/3.16/library/socket.html#socket.socket.sendall).618619Этот метод продолжает отправку в сокет, пока не будут отправлены все данные из *data* или не возникнет ошибка. В случае успеха возвращается `None`. При ошибке вызывается исключение. Кроме того, невозможно определить, какой объём данных (если он был) был успешно обработан принимающей стороной соединения.620621*sock* должен быть неблокирующим сокетом.622623Изменено в версии 3.7: Хотя этот метод всегда документировался как корутинный метод, до Python 3.7 он возвращал [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7, это `async def` метод.624625#### `async loop.sock_sendto(sock, data, address)`626627Отправляет дейтаграмму из *sock* на *address*. Асинхронная версия [`socket.sendto()`](https://python-all.ru/3.16/library/socket.html#socket.socket.sendto).628629Возвращает количество отправленных байт.630631*sock* должен быть неблокирующим сокетом.632633Добавлено в версии 3.12.634635#### `async loop.sock_connect(sock, address)`636637Подключает *sock* к удалённому сокету по адресу *address*.638639Асинхронная версия [`socket.connect()`](https://python-all.ru/3.16/library/socket.html#socket.socket.connect).640641*sock* должен быть неблокирующим сокетом.642643Изменено в версии 3.5.2: `address` больше не требует разрешения. `sock_connect` попытается проверить, разрешён ли уже *address*, вызвав [`socket.inet_pton()`](https://python-all.ru/3.16/library/socket.html#socket.inet_pton). Если нет, [`loop.getaddrinfo()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo) будет использован для разрешения *address*.644645> **См. также**646>647> [`loop.create_connection()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_connection) и [`asyncio.open_connection()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.open_connection).648649#### `async loop.sock_accept(sock)`650651Принимает соединение. Смоделирован по аналогии с блокирующим методом [`socket.accept()`](https://python-all.ru/3.16/library/socket.html#socket.socket.accept).652653Сокет должен быть привязан к адресу и ожидать подключения. Возвращаемое значение – пара `(conn, address)`, где *conn* – это *новый* объект сокета, пригодный для отправки и получения данных по соединению, а *address* – адрес, привязанный к сокету на другом конце соединения.654655*sock* должен быть неблокирующим сокетом.656657Изменено в версии 3.7: Хотя этот метод всегда документировался как корутинный метод, до Python 3.7 он возвращал [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7, это `async def` метод.658659> **См. также**660>661> [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server) и [`start_server()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.start_server).662663#### `async loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)`664665Отправляет файл с использованием высокопроизводительного [`os.sendfile`](https://python-all.ru/3.16/library/os.html#os.sendfile), если возможно. Возвращает общее количество отправленных байт.666667Асинхронная версия [`socket.sendfile()`](https://python-all.ru/3.16/library/socket.html#socket.socket.sendfile).668669*sock* должен быть неблокирующим [`socket.SOCK_STREAM`](https://python-all.ru/3.16/library/socket.html#socket.SOCK_STREAM) [`socket`](https://python-all.ru/3.16/library/socket.html#socket.socket).670671*file* должен быть обычным файловым объектом, открытым в бинарном режиме.672673*offset* указывает, с какого места начинать чтение файла. Если задан, *count* – это общее количество байтов для передачи, в отличие от отправки файла до достижения EOF. Позиция в файле всегда обновляется, даже если этот метод вызывает ошибку, а [`file.tell()`](https://python-all.ru/3.16/library/io.html#io.IOBase.tell) можно использовать для получения фактического количества отправленных байтов.674675*fallback*, если установлено в `True`, заставляет asyncio вручную читать и отправлять файл, когда платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет в Unix).676677Вызывает [`SendfileNotAvailableError`](https://python-all.ru/3.16/library/asyncio-exceptions.html#asyncio.SendfileNotAvailableError), если система не поддерживает системный вызов *sendfile* и *fallback* равен `False`.678679*sock* должен быть неблокирующим сокетом.680681Добавлено в версии 3.7.682683### [DNS](https://python-all.ru/3.16/library/asyncio-eventloop.html#id11)684685#### `async loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)`686687Асинхронная версия [`socket.getaddrinfo()`](https://python-all.ru/3.16/library/socket.html#socket.getaddrinfo).688689#### `async loop.getnameinfo(sockaddr, flags=0)`690691Асинхронная версия [`socket.getnameinfo()`](https://python-all.ru/3.16/library/socket.html#socket.getnameinfo).692693> **Примечание**694>695> Оба метода, *getaddrinfo* и *getnameinfo*, внутренне используют свои синхронные версии через исполнитель пула потоков по умолчанию цикла событий. Когда этот исполнитель насыщен, эти методы могут испытывать задержки, которые высокоуровневые сетевые библиотеки могут сообщать как увеличенные таймауты. Чтобы смягчить это, рассмотрите использование пользовательского исполнителя для других задач пользователя, или установите исполнитель по умолчанию с большим количеством рабочих потоков.696697Изменено в версии 3.7: Оба метода, *getaddrinfo* и *getnameinfo*, всегда документировались как возвращающие корутину, но до Python 3.7 на самом деле возвращали объекты [`asyncio.Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7 оба метода являются корутинами.698699### [Работа с каналами](https://python-all.ru/3.16/library/asyncio-eventloop.html#id12)700701#### `async loop.connect_read_pipe(protocol_factory, pipe)`702703Регистрирует читающий конец канала *pipe* в цикле событий.704705*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола asyncio](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).706707*pipe* – это [объект, подобный файлу](https://python-all.ru/3.16/glossary.html#term-file-object).708709Возвращает пару `(transport, protocol)`, где *транспорт* поддерживает интерфейс [`ReadTransport`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.ReadTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.710711При [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) цикле событий канал *pipe* переводится в неблокирующий режим.712713#### `async loop.connect_write_pipe(protocol_factory, pipe)`714715Регистрирует записывающий конец канала *pipe* в цикле событий.716717*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола asyncio](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol).718719*pipe* – это [объект, подобный файлу](https://python-all.ru/3.16/glossary.html#term-file-object).720721Возвращает пару `(transport, protocol)`, где *транспорт* поддерживает интерфейс [`WriteTransport`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.WriteTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.722723При [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) цикле событий канал *pipe* переводится в неблокирующий режим.724725> **Примечание**726>727> [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) не поддерживает указанные выше методы в Windows. Используйте [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) вместо них в Windows.728729> **См. также**730>731> Методы [`loop.subprocess_exec()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec) и [`loop.subprocess_shell()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.subprocess_shell).732733### [Сигналы Unix](https://python-all.ru/3.16/library/asyncio-eventloop.html#id13)734735#### `loop.add_signal_handler(signum, callback, *args)`736737Устанавливает *колбэк* в качестве обработчика сигнала *signum*, передавая *args* в качестве позиционных аргументов.738739Колбэк будет вызван *loop* вместе с другими поставленными в очередь колбэками и готовыми к запуску корутинами этого цикла событий. В отличие от обработчиков сигналов, зарегистрированных с помощью [`signal.signal()`](https://python-all.ru/3.16/library/signal.html#signal.signal), колбэк, зарегистрированный этой функцией, может взаимодействовать с циклом событий.740741Вызывает [`ValueError`](https://python-all.ru/3.16/library/exceptions.html#ValueError), если номер сигнала недопустим или его невозможно перехватить. Вызывает [`RuntimeError`](https://python-all.ru/3.16/library/exceptions.html#RuntimeError), если возникла проблема при установке обработчика.742743Используйте [`functools.partial()`](https://python-all.ru/3.16/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio-pass-keywords) в *колбэк*.744745Как и [`signal.signal()`](https://python-all.ru/3.16/library/signal.html#signal.signal), эта функция должна вызываться в главном потоке.746747#### `loop.remove_signal_handler(sig)`748749Удаляет обработчик сигнала *sig*.750751Возвращает `True`, если обработчик сигнала был удалён, или `False`, если для указанного сигнала обработчик не был установлен.752753[Доступность](https://python-all.ru/3.16/library/intro.html#availability): Unix.754755> **См. также**756>757> Модуль [`signal`](https://python-all.ru/3.16/library/signal.html#module-signal).758759### [Выполнение кода в пулах потоков или процессов](https://python-all.ru/3.16/library/asyncio-eventloop.html#id14)760761#### `awaitable loop.run_in_executor(executor, func, *args)`762763Планирует вызов *func* в указанном исполнителе с передачей *args* в качестве позиционных аргументов.764765Аргумент *исполнитель* должен быть экземпляром [`concurrent.futures.Executor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.Executor). Если *исполнитель* равен `None`, используется исполнитель по умолчанию. Исполнитель по умолчанию можно задать с помощью [`loop.set_default_executor()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.set_default_executor), иначе будет лениво инициализирован [`concurrent.futures.ThreadPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor), который будет использован в [`run_in_executor()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.run_in_executor) при необходимости.766767Пример:768769```python770import asyncio771import concurrent.futures772773def blocking_io():774 # Файловые операции (например, логирование) могут блокировать цикл событий: выполняйте их в пуле потоков.775 # цикл событий: выполняйте их в пуле потоков.776 with open('/dev/urandom', 'rb') as f:777 return f.read(100)778779def cpu_bound():780 # CPU-ёмкие операции заблокируют цикл событий:781 # в целом предпочтительнее выполнять их в782 # пуле процессов.783 return sum(i * i for i in range(10 ** 7))784785async def main():786 loop = asyncio.get_running_loop()787788 ## Варианты:789790 # 1. Запуск в исполнителе цикла по умолчанию:791 result = await loop.run_in_executor(792 None, blocking_io)793 print('default thread pool', result)794795 # 2. Запуск в пользовательском пуле потоков:796 with concurrent.futures.ThreadPoolExecutor() as pool:797 result = await loop.run_in_executor(798 pool, blocking_io)799 print('custom thread pool', result)800801 # 3. Запуск в пользовательском пуле процессов:802 with concurrent.futures.ProcessPoolExecutor() as pool:803 result = await loop.run_in_executor(804 pool, cpu_bound)805 print('custom process pool', result)806807 # 4. Запуск в пользовательском пуле интерпретаторов:808 with concurrent.futures.InterpreterPoolExecutor() as pool:809 result = await loop.run_in_executor(810 pool, cpu_bound)811 print('custom interpreter pool', result)812813if __name__ == '__main__':814 asyncio.run(main())815```816817Обратите внимание, что защита точки входа (`if __name__ == '__main__'`) требуется для варианта 3 из-за особенностей [`multiprocessing`](https://python-all.ru/3.16/library/multiprocessing.html#module-multiprocessing), используемого в [`ProcessPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor). См. [Безопасный импорт главного модуля](https://python-all.ru/3.16/library/multiprocessing.html#multiprocessing-safe-main-import).818819Этот метод возвращает объект [`asyncio.Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future).820821Используйте [`functools.partial()`](https://python-all.ru/3.16/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio-pass-keywords) в *func*.822823Изменено в версии 3.5.3: `loop.run_in_executor()` больше не настраивает `max_workers` создаваемого исполнителя пула потоков, оставляя настройку по умолчанию самому исполнителю пула потоков ([`ThreadPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor)).824825#### `loop.set_default_executor(executor)`826827Устанавливает *исполнитель* в качестве исполнителя по умолчанию, используемого в [`run_in_executor()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.run_in_executor). *исполнитель* должен быть экземпляром [`ThreadPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor), куда входит [`InterpreterPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.InterpreterPoolExecutor).828829Изменено в версии 3.11: *исполнитель* должен быть экземпляром [`ThreadPoolExecutor`](https://python-all.ru/3.16/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor).830831### [API обработки ошибок](https://python-all.ru/3.16/library/asyncio-eventloop.html#id15)832833Позволяет настраивать обработку исключений в цикле событий.834835#### `loop.set_exception_handler(handler)`836837Устанавливает *handler* в качестве нового обработчика исключений цикла событий.838839Если *handler* равен `None`, будет установлен обработчик исключений по умолчанию. В противном случае *handler* должен быть вызываемым объектом с сигнатурой, соответствующей `(loop, context)`, где `loop` – это ссылка на активный цикл событий, а `context` – это объект `dict`, содержащий сведения об исключении (см. документацию [`call_exception_handler()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_exception_handler) для подробностей о контексте).840841Если обработчик вызывается от имени [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) или [`Handle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Handle), он выполняется в [`contextvars.Context`](https://python-all.ru/3.16/library/contextvars.html#contextvars.Context) этой задачи или колбэка.842843Изменено в версии 3.12: Обработчик может вызываться в [`Context`](https://python-all.ru/3.16/library/contextvars.html#contextvars.Context) задачи или дескриптора, в котором возникло исключение.844845#### `loop.get_exception_handler()`846847Возвращает текущий обработчик исключений или `None`, если не был установлен пользовательский обработчик.848849Добавлено в версии 3.5.2.850851#### `loop.default_exception_handler(context)`852853Обработчик исключений по умолчанию.854855Вызывается при возникновении исключения, если не установлен никакой обработчик. Может быть вызван пользовательским обработчиком, который хочет передать управление поведению по умолчанию.856857Параметр *context* имеет то же значение, что и в [`call_exception_handler()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_exception_handler).858859#### `loop.call_exception_handler(context)`860861Вызывает обработчик исключений текущего цикла событий.862863*context* – это объект `dict`, содержащий следующие ключи (в будущих версиях Python могут появиться новые ключи):864865- ‘message’: сообщение об ошибке;866- 'исключение' (необязательно): объект исключения;867- ‘future’ (необязательно): экземпляр [`asyncio.Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future);868- 'задача' (необязательно): экземпляр [`asyncio.Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task);869- ‘handle’ (необязательно): экземпляр [`asyncio.Handle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Handle);870- 'протокол' (необязательно): экземпляр [Protocol](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-protocol);871- 'транспорт' (необязательно): экземпляр [Transport](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-transport);872- ‘socket’ (необязательно): экземпляр [`socket.socket`](https://python-all.ru/3.16/library/socket.html#socket.socket);873- ‘source\_traceback’ (необязательно): трассировка источника;874- ‘handle\_traceback’ (необязательно): трассировка дескриптора;875- **‘asyncgen’ (необязательно): асинхронный генератор, вызвавший**876877 исключение.878879> **Примечание**880>881> Этот метод не следует переопределять в подклассах циклов событий. Для настраиваемой обработки исключений используйте метод [`set_exception_handler()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.set_exception_handler).882883### [Включение режима отладки](https://python-all.ru/3.16/library/asyncio-eventloop.html#id16)884885#### `loop.get_debug()`886887Возвращает режим отладки ([`bool`](https://python-all.ru/3.16/library/functions.html#bool)) цикла событий.888889Значение по умолчанию – `True`, если переменная окружения [`PYTHONASYNCIODEBUG`](https://python-all.ru/3.16/using/cmdline.html#envvar-PYTHONASYNCIODEBUG) имеет непустое строковое значение, и `False` в противном случае.890891#### `loop.set_debug(enabled: bool)`892893Устанавливает режим отладки цикла событий.894895Изменено в версии 3.7: Новый [режим разработки Python](https://python-all.ru/3.16/library/devmode.html#devmode) теперь также можно использовать для включения режима отладки.896897#### `loop.slow_callback_duration`898899Этот атрибут можно использовать для задания минимальной продолжительности выполнения в секундах, которая считается «медленной». Если режим отладки включен, «медленные» колбэки регистрируются в журнале.900901Значение по умолчанию – 100 миллисекунд.902903> **См. также**904>905> [Режим отладки asyncio](https://python-all.ru/3.16/library/asyncio-dev.html#asyncio-debug-mode).906907### [Запуск подпроцессов](https://python-all.ru/3.16/library/asyncio-eventloop.html#id17)908909Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном коде с async/await рекомендуется вместо них использовать высокоуровневые удобные функции [`asyncio.create_subprocess_shell()`](https://python-all.ru/3.16/library/asyncio-subprocess.html#asyncio.create_subprocess_shell) и [`asyncio.create_subprocess_exec()`](https://python-all.ru/3.16/library/asyncio-subprocess.html#asyncio.create_subprocess_exec).910911> **Примечание**912>913> В Windows цикл событий по умолчанию [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) поддерживает подпроцессы, а [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) – нет. Подробнее см. [Поддержка подпроцессов в Windows](https://python-all.ru/3.16/library/asyncio-platforms.html#asyncio-windows-subprocess).914915#### `async loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)`916917Создаёт подпроцесс из одного или нескольких строковых аргументов, заданных параметром *args*.918919Параметр *args* должен быть списком строк, представленным следующим образом:920921- [`str`](https://python-all.ru/3.16/library/stdtypes.html#str);922- или [`bytes`](https://python-all.ru/3.16/library/stdtypes.html#bytes), закодированная в [кодировку файловой системы](https://python-all.ru/3.16/library/os.html#filesystem-encoding).923924Первая строка указывает исполняемый файл программы, а остальные строки задают аргументы. Вместе строковые аргументы образуют `argv` программы.925926Это похоже на класс [`subprocess.Popen`](https://python-all.ru/3.16/library/subprocess.html#subprocess.Popen) из стандартной библиотеки, который вызывается с `shell=False` и списком строк, передаваемых в качестве первого аргумента; однако, если `Popen` принимает один аргумент – список строк, *subprocess\_exec* принимает несколько строковых аргументов.927928Параметр *protocol\_factory* должен быть вызываемым объектом, возвращающим подкласс класса [`asyncio.SubprocessProtocol`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.SubprocessProtocol).929930Другие параметры:931932- *stdin* может принимать одно из следующих значений:933934 - файлоподобный объект935 - существующий файловый дескриптор (положительное целое число), например, созданный с помощью [`os.pipe()`](https://python-all.ru/3.16/library/os.html#os.pipe)936 - константа [`subprocess.PIPE`](https://python-all.ru/3.16/library/subprocess.html#subprocess.PIPE) (по умолчанию), которая создаст новый канал и подключит его,937 - значение `None`, которое заставляет подпроцесс наследовать файловый дескриптор от этого процесса938 - константа [`subprocess.DEVNULL`](https://python-all.ru/3.16/library/subprocess.html#subprocess.DEVNULL), указывающая, что будет использоваться специальный файл [`os.devnull`](https://python-all.ru/3.16/library/os.html#os.devnull)939- *stdout* может принимать одно из следующих значений:940941 - файлоподобный объект942 - константа [`subprocess.PIPE`](https://python-all.ru/3.16/library/subprocess.html#subprocess.PIPE) (по умолчанию), которая создаст новый канал и подключит его,943 - значение `None`, которое заставляет подпроцесс наследовать файловый дескриптор от этого процесса944 - константа [`subprocess.DEVNULL`](https://python-all.ru/3.16/library/subprocess.html#subprocess.DEVNULL), указывающая, что будет использоваться специальный файл [`os.devnull`](https://python-all.ru/3.16/library/os.html#os.devnull)945- *stderr* может принимать одно из следующих значений:946947 - файлоподобный объект948 - константа [`subprocess.PIPE`](https://python-all.ru/3.16/library/subprocess.html#subprocess.PIPE) (по умолчанию), которая создаст новый канал и подключит его,949 - значение `None`, которое заставляет подпроцесс наследовать файловый дескриптор от этого процесса950 - константа [`subprocess.DEVNULL`](https://python-all.ru/3.16/library/subprocess.html#subprocess.DEVNULL), указывающая, что будет использоваться специальный файл [`os.devnull`](https://python-all.ru/3.16/library/os.html#os.devnull)951 - константа [`subprocess.STDOUT`](https://python-all.ru/3.16/library/subprocess.html#subprocess.STDOUT), которая подключает поток стандартной ошибки к потоку стандартного вывода процесса952- Все остальные именованные аргументы передаются в [`subprocess.Popen`](https://python-all.ru/3.16/library/subprocess.html#subprocess.Popen) без интерпретации, за исключением *bufsize*, *universal\_newlines*, *shell*, *text*, *encoding* и *errors*, которые не должны указываться вовсе.953954 API подпроцессов `asyncio` не поддерживает декодирование потоков как текст. Для преобразования байтов, возвращаемых из потока, в текст можно использовать [`bytes.decode()`](https://python-all.ru/3.16/library/stdtypes.html#bytes.decode).955956Если файлоподобный объект, переданный как *stdin*, *stdout* или *stderr*, представляет собой канал, то другой конец этого канала должен быть зарегистрирован с помощью [`connect_write_pipe()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.connect_write_pipe) или [`connect_read_pipe()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.connect_read_pipe) для использования с циклом событий.957958Описание остальных аргументов см. в конструкторе класса [`subprocess.Popen`](https://python-all.ru/3.16/library/subprocess.html#subprocess.Popen).959960Возвращает пару `(transport, protocol)`, где *транспорт* соответствует базовому классу [`asyncio.SubprocessTransport`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.SubprocessTransport), а *протокол* – это объект, созданный с помощью *protocol\_factory*.961962Если транспорт закрыт или собран сборщиком мусора, дочерний процесс завершается, если он всё ещё выполняется.963964#### `async loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)`965966Создаёт подпроцесс из *cmd*, который может быть строкой [`str`](https://python-all.ru/3.16/library/stdtypes.html#str) или [`bytes`](https://python-all.ru/3.16/library/stdtypes.html#bytes), закодированной в [кодировку файловой системы](https://python-all.ru/3.16/library/os.html#filesystem-encoding), используя синтаксис командной оболочки платформы («shell»).967968Это похоже на [`subprocess.Popen`](https://python-all.ru/3.16/library/subprocess.html#subprocess.Popen) класс из стандартной библиотеки, вызываемый с помощью `shell=True`.969970Параметр *protocol\_factory* должен быть вызываемым объектом, возвращающим подкласс класса [`SubprocessProtocol`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.SubprocessProtocol).971972Подробнее об остальных аргументах см. в [`subprocess_exec()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec).973974Возвращает пару из `(transport, protocol)`, где *транспорт* соответствует базовому классу [`SubprocessTransport`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.SubprocessTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.975976Если транспорт закрыт или удалён сборщиком мусора, дочерний процесс завершается, если он ещё выполняется.977978> **Примечание**979>980> Ответственность за то, чтобы все пробельные и специальные символы были правильно экранированы, лежит на приложении – это позволяет избежать уязвимостей [инъекции команд оболочки](https://python-all.ru/3.16/library/asyncio-eventloop.html). Для корректного экранирования пробелов и спецсимволов в строках, используемых при построении команд оболочки, можно применить функцию [`shlex.quote()`](https://python-all.ru/3.16/library/shlex.html#shlex.quote).981982## Обработчики колбэков983984#### `class asyncio.Handle`985986Объект-обёртка колбэка, возвращаемый [`loop.call_soon()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon), [`loop.call_soon_threadsafe()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe).987988#### `get_context()`989990Возвращает объект [`contextvars.Context`](https://python-all.ru/3.16/library/contextvars.html#contextvars.Context), связанный с обработчиком.991992Добавлено в версии 3.12.993994#### `cancel()`995996Отменяет колбэк. Если колбэк уже был отменён или выполнен, этот метод не делает ничего.997998#### `cancelled()`9991000Возвращает `True`, если колбэк был отменён.10011002Добавлено в версии 3.7.10031004#### `class asyncio.TimerHandle`10051006Объект-обёртка колбэка, возвращаемый [`loop.call_later()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_later) и [`loop.call_at()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_at).10071008Этот класс является подклассом [`Handle`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Handle).10091010#### `when()`10111012Возвращает запланированное время выполнения колбэка в секундах [`float`](https://python-all.ru/3.16/library/functions.html#float).10131014Время – абсолютная временная метка, использующая ту же систему отсчёта, что и [`loop.time()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.time).10151016Добавлено в версии 3.7.10171018## Объекты сервера10191020Объекты сервера создаются функциями [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server), [`loop.create_unix_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_unix_server), [`start_server()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.start_server) и [`start_unix_server()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.start_unix_server).10211022Не следует создавать экземпляры класса [`Server`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server) напрямую.10231024#### `class asyncio.Server`10251026Объекты *Server* являются асинхронными контекстными менеджерами. При использовании в операторе `async with` гарантируется, что объект Server будет закрыт и не будет принимать новые подключения после завершения оператора `async with`:10271028```python1029srv = await loop.create_server(...)10301031async with srv:1032 # некоторый код10331034# На данный момент srv закрыт и больше не принимает новые соединения.1035```10361037Изменено в версии 3.7: Объект Server является асинхронным контекстным менеджером начиная с Python 3.7.10381039Изменено в версии 3.11: Этот класс стал общедоступным как `asyncio.Server` в Python 3.9.11, 3.10.3 и 3.11.10401041#### `close()`10421043Прекращает обслуживание: закрывает слушающие сокеты и устанавливает атрибут [`sockets`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.sockets) в `None`.10441045Сокеты, представляющие существующие входящие клиентские подключения, остаются открытыми.10461047Сервер закрывается асинхронно; используйте корутину [`wait_closed()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.wait_closed), чтобы дождаться закрытия сервера (когда больше не будет активных подключений).10481049#### `close_clients()`10501051Закрывает все существующие входящие клиентские соединения.10521053Вызывает [`close()`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.BaseTransport.close) на всех связанных транспортах.10541055[`close()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.close) следует вызывать перед `close_clients()` при закрытии сервера, чтобы избежать состояний гонки с подключающимися новыми клиентами.10561057Добавлено в версии 3.13.10581059#### `abort_clients()`10601061Закрывает все существующие входящие клиентские соединения немедленно, не дожидаясь завершения ожидающих операций.10621063Вызывает [`abort()`](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio.WriteTransport.abort) на всех связанных транспортах.10641065[`close()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.close) следует вызывать перед `abort_clients()` при закрытии сервера, чтобы избежать состояний гонки с подключающимися новыми клиентами.10661067Добавлено в версии 3.13.10681069#### `get_loop()`10701071Возвращает цикл событий, связанный с объектом сервера.10721073Добавлено в версии 3.7.10741075#### `async start_serving()`10761077Начинает принимать соединения.10781079Этот метод идемпотентен, поэтому его можно вызывать, когда сервер уже работает.10801081Параметр *start\_serving*, передаваемый только по ключевому слову, в [`loop.create_server()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_server) и [`asyncio.start_server()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.start_server) позволяет создать объект Server, который изначально не принимает соединения. В этом случае можно использовать `Server.start_serving()` или [`Server.serve_forever()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.serve_forever), чтобы заставить Server начать принимать соединения.10821083Добавлено в версии 3.7.10841085#### `async serve_forever()`10861087Начинает принимать соединения до отмены корутины. Отмена задачи `serve_forever` приводит к закрытию сервера.10881089Этот метод можно вызывать, если сервер уже принимает соединения. Для одного объекта *Server* может существовать только одна задача `serve_forever`.10901091Пример:10921093```python1094async def client_connected(reader, writer):1095 # Общение с клиентом через1096 # потоки чтения/записи. Например:1097 await reader.readline()10981099async def main(host, port):1100 srv = await asyncio.start_server(1101 client_connected, host, port)1102 await srv.serve_forever()11031104asyncio.run(main('127.0.0.1', 0))1105```11061107Добавлено в версии 3.7.11081109#### `is_serving()`11101111Возвращает `True`, если сервер принимает новые соединения.11121113Добавлено в версии 3.7.11141115#### `async wait_closed()`11161117Ожидает завершения метода [`close()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.Server.close) и всех активных соединений.11181119#### `sockets`11201121Список объектов, подобных сокетам, `asyncio.trsock.TransportSocket`, на которых сервер прослушивает соединения.11221123Изменено в версии 3.7: До Python 3.7 `Server.sockets` возвращал внутренний список серверных сокетов напрямую. В версии 3.7 возвращается копия этого списка.11241125## Реализации цикла событий11261127asyncio поставляется с двумя различными реализациями цикла событий: [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) и [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).11281129По умолчанию asyncio настроен на использование [`EventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.EventLoop).11301131#### `class asyncio.SelectorEventLoop`11321133Подкласс [`AbstractEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.AbstractEventLoop), основанный на модуле [`selectors`](https://python-all.ru/3.16/library/selectors.html#module-selectors).11341135Использует наиболее эффективный *селектор*, доступный для данной платформы. Также можно вручную настроить конкретную реализацию селектора:11361137```python1138import asyncio1139import selectors11401141async def main():1142 ...11431144loop_factory = lambda: asyncio.SelectorEventLoop(selectors.SelectSelector())1145asyncio.run(main(), loop_factory=loop_factory)1146```11471148[Доступность](https://python-all.ru/3.16/library/intro.html#availability): Unix, Windows.11491150#### `class asyncio.ProactorEventLoop`11511152A subclass of [`AbstractEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.AbstractEventLoop) for Windows that uses “I/O Completion Ports” (IOCP).11531154[Доступность](https://python-all.ru/3.16/library/intro.html#availability): Windows.11551156> **См. также**1157>1158> [MSDN documentation on I/O Completion Ports](https://python-all.ru/3.16/library/asyncio-eventloop.html).11591160#### `class asyncio.EventLoop`11611162> Псевдоним наиболее эффективного доступного подкласса [`AbstractEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.AbstractEventLoop) для данной платформы.1163>1164> Это псевдоним [`SelectorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) на Unix и [`ProactorEventLoop`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) на Windows.11651166Добавлено в версии 3.13.11671168#### `class asyncio.AbstractEventLoop`11691170Абстрактный базовый класс для циклов событий, совместимых с asyncio.11711172Раздел [Методы цикла событий](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio-event-loop-methods) перечисляет все методы, которые должна определять альтернативная реализация `AbstractEventLoop` .11731174## Примеры11751176Обратите внимание, что все примеры в этом разделе **намеренно** показывают, как использовать низкоуровневые API цикла событий, такие как [`loop.run_forever()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.run_forever) и [`loop.call_soon()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon). Современные приложения asyncio редко требуют такого стиля написания; рекомендуется использовать высокоуровневые функции, такие как [`asyncio.run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run).11771178### Hello World с call\_soon()11791180Пример использования метода [`loop.call_soon()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_soon) для планирования колбэка. Колбэк выводит `"Hello World"`, а затем останавливает цикл событий:11811182```python1183import asyncio11841185def hello_world(loop):1186 """Колбэк для вывода 'Hello World' и остановки цикла событий"""1187 print('Hello World')1188 loop.stop()11891190loop = asyncio.new_event_loop()11911192# Запланировать вызов hello_world()1193loop.call_soon(hello_world, loop)11941195# Блокирующий вызов прерван loop.stop()1196try:1197 loop.run_forever()1198finally:1199 loop.close()1200```12011202> **См. также**1203>1204> Аналогичный [пример Hello World](https://python-all.ru/3.16/library/asyncio-task.html#coroutine), созданный с помощью корутины и функции [`run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run).12051206### Отображение текущей даты с помощью call\_later()12071208Пример колбэка, выводящего текущую дату каждую секунду. Колбэк использует метод [`loop.call_later()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.call_later) для повторного планирования самого себя через 5 секунд, а затем останавливает цикл событий:12091210```python1211import asyncio1212import datetime as dt12131214def display_date(end_time, loop):1215 print(dt.datetime.now())1216 if (loop.time() + 1.0) < end_time:1217 loop.call_later(1, display_date, end_time, loop)1218 else:1219 loop.stop()12201221loop = asyncio.new_event_loop()12221223# Запланировать первый вызов display_date()1224end_time = loop.time() + 5.01225loop.call_soon(display_date, end_time, loop)12261227# Блокирующий вызов прерван loop.stop()1228try:1229 loop.run_forever()1230finally:1231 loop.close()1232```12331234> **См. также**1235>1236> Аналогичный [пример с текущей датой](https://python-all.ru/3.16/library/asyncio-task.html#asyncio-example-sleep), созданный с помощью корутины и функции [`run()`](https://python-all.ru/3.16/library/asyncio-runner.html#asyncio.run).12371238### Наблюдение за файловым дескриптором на события чтения12391240Ожидание, пока файловый дескриптор не получит некоторые данные, с помощью метода [`loop.add_reader()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.add_reader), после чего цикл событий закрывается:12411242```python1243import asyncio1244from socket import socketpair12451246# Создать пару связанных файловых дескрипторов1247rsock, wsock = socketpair()12481249loop = asyncio.new_event_loop()12501251def reader():1252 data = rsock.recv(100)1253 print("Received:", data.decode())12541255 # Готово: отменить регистрацию файлового дескриптора1256 loop.remove_reader(rsock)12571258 # Остановить цикл событий1259 loop.stop()12601261# Зарегистрировать файловый дескриптор для события чтения1262loop.add_reader(rsock, reader)12631264# Симулировать получение данных из сети1265loop.call_soon(wsock.send, 'abc'.encode())12661267try:1268 # Запустить цикл событий1269 loop.run_forever()1270finally:1271 # Готово. Закрыть сокеты и цикл событий.1272 rsock.close()1273 wsock.close()1274 loop.close()1275```12761277> **См. также**1278>1279> - Аналогичный [пример](https://python-all.ru/3.16/library/asyncio-protocol.html#asyncio-example-create-connection) с использованием транспортов, протоколов и метода [`loop.create_connection()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.create_connection).1280> - Ещё один аналогичный [пример](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio-example-create-connection-streams) с использованием высокоуровневой функции [`asyncio.open_connection()`](https://python-all.ru/3.16/library/asyncio-stream.html#asyncio.open_connection) и потоков данных.12811282### Установка обработчиков сигналов SIGINT и SIGTERM12831284(Этот `signal` пример работает только на Unix.)12851286Регистрация обработчиков для сигналов [`SIGINT`](https://python-all.ru/3.16/library/signal.html#signal.SIGINT) и [`SIGTERM`](https://python-all.ru/3.16/library/signal.html#signal.SIGTERM) с помощью метода [`loop.add_signal_handler()`](https://python-all.ru/3.16/library/asyncio-eventloop.html#asyncio.loop.add_signal_handler):12871288```python1289import asyncio1290import functools1291import os1292import signal12931294def ask_exit(signame, loop):1295 print("got signal %s: exit" % signame)1296 loop.stop()12971298async def main():1299 loop = asyncio.get_running_loop()13001301 for signame in {'SIGINT', 'SIGTERM'}:1302 loop.add_signal_handler(1303 getattr(signal, signame),1304 functools.partial(ask_exit, signame, loop))13051306 await asyncio.sleep(3600)13071308print("Event loop running for 1 hour, press Ctrl+C to interrupt.")1309print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")13101311asyncio.run(main())1312```1313