asyncio-eventloop.md
1> **Источник:** https://python-all.ru/3.7/library/asyncio-eventloop.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Цикл событий89Предисловие1011Цикл событий – ядро каждого приложения asyncio. Циклы событий выполняют асинхронные задачи и колбэки, осуществляют сетевые операции ввода-вывода и запускают подпроцессы.1213Разработчикам приложений обычно следует использовать высокоуровневые функции asyncio, такие как [`asyncio.run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run), и редко требуется обращаться к объекту цикла или вызывать его методы. Этот раздел предназначен в основном для авторов низкоуровневого кода, библиотек и фреймворков, которым нужен более тонкий контроль над поведением цикла событий.1415Получение цикла событий1617Следующие низкоуровневые функции можно использовать для получения, установки или создания цикла событий:1819#### `asyncio.get_running_loop()`2021Возвращает работающий цикл событий в текущем потоке ОС.2223Если нет работающего цикла событий, вызывается [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError). Эту функцию можно вызывать только из корутины или колбэка.2425Добавлено в версии 3.7.2627#### `asyncio.get_event_loop()`2829Получить текущий цикл событий.3031Если в текущем потоке ОС не установлен текущий цикл событий, этот поток является главным, и функция [`set_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.set_event_loop) ещё не вызывалась, asyncio создаст новый цикл событий и сделает его текущим.3233Поскольку поведение этой функции довольно сложное (особенно при использовании пользовательских политик цикла событий), в корутинах и колбэках предпочтительнее использовать функцию [`get_running_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_running_loop), а не [`get_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_event_loop).3435Также рассмотрите возможность использования функции [`asyncio.run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run) вместо низкоуровневых функций для ручного создания и закрытия цикла событий.3637#### `asyncio.set_event_loop(loop)`3839Устанавливает *loop* в качестве текущего цикла событий для текущего потока ОС.4041#### `asyncio.new_event_loop()`4243Создаёт новый объект цикла событий.4445Обратите внимание, что поведение функций [`get_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_event_loop), [`set_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.set_event_loop) и [`new_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.new_event_loop) можно изменить, [установив пользовательскую политику цикла событий](https://python-all.ru/3.7/library/asyncio-policy.html#asyncio-policies).4647Содержание4849Эта страница документации содержит следующие разделы:5051- Раздел [Методы цикла событий](https://python-all.ru/3.7/library/asyncio-eventloop.html#event-loop-methods) – это справочная документация по API цикла событий;52- Раздел [Обработчики колбэков](https://python-all.ru/3.7/library/asyncio-eventloop.html#callback-handles) документирует экземпляры [`Handle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Handle) и [`TimerHandle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.TimerHandle), которые возвращаются из методов планирования, таких как [`loop.call_soon()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_soon) и [`loop.call_later()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_later);53- Раздел [Объекты сервера](https://python-all.ru/3.7/library/asyncio-eventloop.html#server-objects) документирует типы, возвращаемые методами цикла событий, такими как [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server);54- Раздел [Реализации цикла событий](https://python-all.ru/3.7/library/asyncio-eventloop.html#event-loop-implementations) документирует классы [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) и [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop);55- Раздел [Примеры](https://python-all.ru/3.7/library/asyncio-eventloop.html#examples) показывает, как работать с некоторыми API цикла событий.5657## Методы цикла событий5859Циклы событий имеют **низкоуровневые** API для следующего:6061- [Запуск и остановка цикла событий](https://python-all.ru/3.7/library/asyncio-eventloop.html#running-and-stopping-the-loop)62- [Планирование колбэков](https://python-all.ru/3.7/library/asyncio-eventloop.html#scheduling-callbacks)63- [Планирование отложенных колбэков](https://python-all.ru/3.7/library/asyncio-eventloop.html#scheduling-delayed-callbacks)64- [Создание Future и задач](https://python-all.ru/3.7/library/asyncio-eventloop.html#creating-futures-and-tasks)65- [Открытие сетевых соединений](https://python-all.ru/3.7/library/asyncio-eventloop.html#opening-network-connections)66- [Создание сетевых серверов](https://python-all.ru/3.7/library/asyncio-eventloop.html#creating-network-servers)67- [Передача файлов](https://python-all.ru/3.7/library/asyncio-eventloop.html#transferring-files)68- [Обновление TLS](https://python-all.ru/3.7/library/asyncio-eventloop.html#tls-upgrade)69- [Наблюдение за файловыми дескрипторами](https://python-all.ru/3.7/library/asyncio-eventloop.html#watching-file-descriptors)70- [Работа с объектами сокетов напрямую](https://python-all.ru/3.7/library/asyncio-eventloop.html#working-with-socket-objects-directly)71- [DNS](https://python-all.ru/3.7/library/asyncio-eventloop.html#dns)72- [Работа с каналами](https://python-all.ru/3.7/library/asyncio-eventloop.html#working-with-pipes)73- [Сигналы Unix](https://python-all.ru/3.7/library/asyncio-eventloop.html#unix-signals)74- [Выполнение кода в пулах потоков или процессов](https://python-all.ru/3.7/library/asyncio-eventloop.html#executing-code-in-thread-or-process-pools)75- [API обработки ошибок](https://python-all.ru/3.7/library/asyncio-eventloop.html#error-handling-api)76- [Включение режима отладки](https://python-all.ru/3.7/library/asyncio-eventloop.html#enabling-debug-mode)77- [Запуск подпроцессов](https://python-all.ru/3.7/library/asyncio-eventloop.html#running-subprocesses)7879### [Запуск и остановка цикла](https://python-all.ru/3.7/library/asyncio-eventloop.html#id1)8081#### `loop.run_until_complete(future)`8283Выполняется до тех пор, пока *future* (экземпляр [`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future)) не завершится.8485Если аргумент является [объектом корутины](https://python-all.ru/3.7/library/asyncio-task.html#coroutine), он неявно планируется для выполнения как [`asyncio.Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task).8687Возвращает результат Future или возбуждает его исключение.8889#### `loop.run_forever()`9091Запускает цикл событий до вызова [`stop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.stop).9293Если [`stop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.stop) вызывается до вызова [`run_forever()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_forever), цикл один раз опросит I/O-селектор с нулевым таймаутом, выполнит все колбэки, запланированные в ответ на события ввода-вывода (и уже запланированные), а затем завершится.9495Если [`stop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.stop) вызывается во время выполнения [`run_forever()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_forever), цикл выполнит текущий пакет колбэков и завершится. Обратите внимание: новые колбэки, запланированные другими колбэками, в этом случае не запустятся; вместо этого они будут выполнены при следующем вызове [`run_forever()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_forever) или [`run_until_complete()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_until_complete).9697#### `loop.stop()`9899Останавливает цикл событий.100101#### `loop.is_running()`102103Возвращает `True`, если цикл событий в данный момент выполняется.104105#### `loop.is_closed()`106107Возвращает `True`, если цикл событий был закрыт.108109#### `loop.close()`110111Закрывает цикл событий.112113Цикл не должен выполняться при вызове этой функции. Все ожидающие колбэки будут отброшены.114115Этот метод очищает все очереди и завершает работу исполнителя, но не ожидает завершения исполнителя.116117Этот метод идемпотентен и необратим. После закрытия цикла событий не следует вызывать другие методы.118119#### `coroutine loop.shutdown_asyncgens()`120121Планирует закрытие всех открытых [асинхронных генераторов](https://python-all.ru/3.7/glossary.html#term-asynchronous-generator) с помощью вызова [`aclose()`](https://python-all.ru/3.7/reference/expressions.html#agen.aclose). После вызова этого метода цикл событий будет выдавать предупреждение, если выполняется итерация нового асинхронного генератора. Это следует использовать для надёжного завершения всех запланированных асинхронных генераторов.122123Обратите внимание: вызывать эту функцию не нужно, если используется [`asyncio.run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run).124125Пример:126127```python128try:129 loop.run_forever()130finally:131 loop.run_until_complete(loop.shutdown_asyncgens())132 loop.close()133```134135Новое в версии 3.6.136137### [Планирование колбэков](https://python-all.ru/3.7/library/asyncio-eventloop.html#id2)138139#### `loop.call_soon(callback, *args, context=None)`140141Планирует вызов *колбэка* с аргументами *args* на следующей итерации цикла событий.142143Колбэки вызываются в порядке их регистрации. Каждый колбэк будет вызван ровно один раз.144145Необязательный аргумент *context* (только ключевой) позволяет указать пользовательский [`contextvars.Context`](https://python-all.ru/3.7/library/contextvars.html#contextvars.Context) для выполнения *колбэка*. Если *context* не указан, используется текущий контекст.146147Возвращается экземпляр [`asyncio.Handle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Handle), который можно использовать позже для отмены колбэка.148149Этот метод не потокобезопасен.150151#### `loop.call_soon_threadsafe(callback, *args, context=None)`152153Потокобезопасный вариант [`call_soon()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_soon). Должен использоваться для планирования колбэков *из другого потока*.154155См. раздел [concurrency and multithreading](https://python-all.ru/3.7/library/asyncio-dev.html#asyncio-multithreading) документации.156157Изменено в версии 3.7: Добавлен параметр *context* (только ключевое слово). Подробнее см. [**PEP 567**](https://python-all.ru/3.7/library/asyncio-eventloop.html).158159> **Примечание**160>161> Большинство функций планирования [`asyncio`](https://python-all.ru/3.7/library/asyncio.html#module-asyncio) не позволяют передавать именованные аргументы. Для этого используйте [`functools.partial()`](https://python-all.ru/3.7/library/functools.html#functools.partial):162>163> ```python164> # запланирует "print("Hello", flush=True)"165> loop.call_soon(166> functools.partial(print, "Hello", flush=True))167> ```168>169> Использование partial-объектов обычно удобнее лямбд, так как asyncio может лучше отображать partial-объекты в сообщениях отладки и ошибок.170171### [Планирование отложенных колбэков](https://python-all.ru/3.7/library/asyncio-eventloop.html#id3)172173Цикл событий предоставляет механизмы для планирования вызова функций-колбэков в некоторый момент в будущем. Цикл событий использует монотонные часы для отслеживания времени.174175#### `loop.call_later(delay, callback, *args, context=None)`176177Планирует вызов *колбэк* через заданное количество секунд *delay* (может быть целым числом или числом с плавающей запятой).178179Возвращается экземпляр [`asyncio.TimerHandle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.TimerHandle), который можно использовать для отмены колбэка.180181*колбэк* будет вызван ровно один раз. Если два колбэка запланированы на одно и то же время, порядок их вызова не определён.182183Необязательные позиционные аргументы *args* будут переданы колбэку при его вызове. Если нужно передать колбэку именованные аргументы, используйте [`functools.partial()`](https://python-all.ru/3.7/library/functools.html#functools.partial).184185Необязательный аргумент *context* (только ключевой) позволяет указать пользовательский [`contextvars.Context`](https://python-all.ru/3.7/library/contextvars.html#contextvars.Context) для выполнения *колбэка*. Если *context* не указан, используется текущий контекст.186187Изменено в версии 3.7: Добавлен параметр *context* (только ключевое слово). Подробнее см. [**PEP 567**](https://python-all.ru/3.7/library/asyncio-eventloop.html).188189Изменено в версии 3.7.1: В Python 3.7.0 и более ранних версиях при использовании реализации цикла событий по умолчанию значение *delay* не могло превышать один день. Это исправлено в Python 3.7.1.190191#### `loop.call_at(when, callback, *args, context=None)`192193Планирует вызов *колбэк* в заданную абсолютную временную метку *when* (целое число или число с плавающей запятой), используя ту же временную шкалу, что и [`loop.time()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.time).194195Поведение этого метода аналогично [`call_later()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_later).196197Возвращается экземпляр [`asyncio.TimerHandle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.TimerHandle), который можно использовать для отмены колбэка.198199Изменено в версии 3.7: Добавлен параметр *context* (только ключевое слово). Подробнее см. [**PEP 567**](https://python-all.ru/3.7/library/asyncio-eventloop.html).200201Изменено в версии 3.7.1: В Python 3.7.0 и более ранних версиях при использовании реализации цикла событий по умолчанию разница между *when* и текущим временем не могла превышать один день. Это исправлено в Python 3.7.1.202203#### `loop.time()`204205Возвращает текущее время, как значение [`float`](https://python-all.ru/3.7/library/functions.html#float), в соответствии с внутренними монотонными часами цикла событий.206207> **Примечание**208>209> Изменено в версии 3.8: В Python 3.7 и более ранних версиях таймауты (относительная *задержка* или абсолютное значение *when*) не должны были превышать одного дня. Это было исправлено в Python 3.8.210211> **См. также**212>213> Функция [`asyncio.sleep()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.sleep).214215### [Создание Future и задач](https://python-all.ru/3.7/library/asyncio-eventloop.html#id4)216217#### `loop.create_future()`218219Создаёт объект [`asyncio.Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future), привязанный к циклу событий.220221Это предпочтительный способ создания Future в asyncio. Он позволяет сторонним циклам событий предоставлять альтернативные реализации объекта Future (с лучшей производительностью или инструментарием).222223Новое в версии 3.5.2.224225#### `loop.create_task(coro)`226227Планирует выполнение [корутины](https://python-all.ru/3.7/library/asyncio-task.html#coroutine). Возвращает объект [`Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task).228229Сторонние циклы событий могут использовать свой собственный подкласс [`Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task) для совместимости. В этом случае тип результата является подклассом [`Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task).230231#### `loop.set_task_factory(factory)`232233Устанавливает фабрику задач, которая будет использоваться [`loop.create_task()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_task).234235Если *factory* равен `None`, будет установлена фабрика задач по умолчанию. В противном случае *factory* должен быть *вызываемым объектом* с сигнатурой, соответствующей `(loop, coro)`, где *loop* – это ссылка на активный цикл событий, а *coro* – объект корутины. Такой вызываемый объект должен возвращать объект, совместимый с [`asyncio.Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future).236237#### `loop.get_task_factory()`238239Возвращает фабрику задач или `None`, если используется стандартная.240241### [Открытие сетевых соединений](https://python-all.ru/3.7/library/asyncio-eventloop.html#id5)242243#### `coroutine loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None)`244245Открывает потоковое транспортное соединение по заданному адресу, указанному в *host* и *port*.246247Семейство сокетов может быть [`AF_INET`](https://python-all.ru/3.7/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.7/library/socket.html#socket.AF_INET6) в зависимости от *host* (или аргумента *family*, если он передан).248249Тип сокета будет [`SOCK_STREAM`](https://python-all.ru/3.7/library/socket.html#socket.SOCK_STREAM).250251*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола asyncio](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).252253Этот метод попытается установить соединение в фоновом режиме. При успехе он возвращает пару `(transport, protocol)`.254255Хронологическая последовательность выполняемой операции следующая:2562571. Соединение устанавливается, и для него создаётся [транспорт](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-transport) .2582. *protocol\_factory* вызывается без аргументов и должен вернуть экземпляр [протокола](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).2593. Экземпляр протокола связывается с транспортом вызовом его метода [`connection_made()`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.BaseProtocol.connection_made).2604. При успехе возвращается кортеж `(transport, protocol)`.261262Созданный транспорт представляет собой двунаправленный поток данных, зависящий от реализации.263264Остальные аргументы:265266- *ssl*: если указан и не равен false, создаётся транспорт SSL/TLS (по умолчанию создаётся обычный TCP-транспорт). Если *ssl* является объектом [`ssl.SSLContext`](https://python-all.ru/3.7/library/ssl.html#ssl.SSLContext), этот контекст используется для создания транспорта; если *ssl* равно [`True`](https://python-all.ru/3.7/library/constants.html#True), используется контекст по умолчанию, возвращаемый из [`ssl.create_default_context()`](https://python-all.ru/3.7/library/ssl.html#ssl.create_default_context).267268 > **См. также**269 >270 > [Вопросы безопасности SSL/TLS](https://python-all.ru/3.7/library/ssl.html#ssl-security)271- *server\_hostname* задаёт или переопределяет имя хоста, с которым будет сверяться сертификат целевого сервера. Следует передавать только если *ssl* не равен `None`. По умолчанию используется значение аргумента *host*. Если *host* пуст, значения по умолчанию нет, и необходимо передать значение для *server\_hostname*. Если *server\_hostname* – пустая строка, сопоставление имён хостов отключается (что представляет серьёзную угрозу безопасности, допуская атаки «человек посередине»).272- *family*, *proto*, *flags* – необязательные семейство адресов, протокол и флаги, которые передаются в getaddrinfo() для разрешения *host*. Если заданы, все они должны быть целыми числами из соответствующих констант модуля [`socket`](https://python-all.ru/3.7/library/socket.html#module-socket).273- Если задан *sock*, он должен быть существующим, уже подключённым объектом [`socket.socket`](https://python-all.ru/3.7/library/socket.html#socket.socket), который будет использоваться транспортом. Если *sock* задан, ни один из параметров *host*, *port*, *family*, *proto*, *flags* и *local\_addr* не должен быть указан.274- *local\_addr*, если задан, представляет собой кортеж `(local_host, local_port)`, используемый для привязки сокета локально. *local\_host* и *local\_port* разрешаются с помощью `getaddrinfo()`, аналогично *host* и *port*.275- *ssl\_handshake\_timeout* (для TLS-соединения) – время в секундах ожидания завершения рукопожатия TLS перед разрывом соединения. `60.0` секунд, если `None` (по умолчанию).276277Новое в версии 3.7: параметр *ssl\_handshake\_timeout*.278279Изменено в версии 3.6: Параметр сокета `TCP_NODELAY` теперь устанавливается по умолчанию для всех TCP-соединений.280281Изменено в версии 3.5: Добавлена поддержка SSL/TLS в [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).282283> **См. также**284>285> Функция [`open_connection()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.open_connection) является высокоуровневой альтернативой API. Она возвращает пару ([`StreamReader`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.StreamReader), [`StreamWriter`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.StreamWriter)), которую можно использовать непосредственно в коде с async/await.286287#### `coroutine loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None)`288289> **Примечание**290>291> Параметр *reuse\_address* больше не поддерживается, так как использование `SO_REUSEADDR` создаёт серьёзную угрозу безопасности для UDP. Явная передача `reuse_address=True` вызовет исключение.292>293> Когда несколько процессов с разными UID назначают сокеты одному и тому же адресу UDP-сокета с помощью `SO_REUSEADDR`, входящие пакеты могут случайным образом распределяться между сокетами.294>295> На поддерживаемых платформах *reuse\_port* можно использовать как замену аналогичной функциональности. С *reuse\_port* используется `SO_REUSEPORT`, что не позволяет процессам с разными UID назначать сокеты на один и тот же адрес сокета.296297Создать датаграммное соединение.298299Семейство сокетов может быть одним из [`AF_INET`](https://python-all.ru/3.7/library/socket.html#socket.AF_INET), [`AF_INET6`](https://python-all.ru/3.7/library/socket.html#socket.AF_INET6) или [`AF_UNIX`](https://python-all.ru/3.7/library/socket.html#socket.AF_UNIX), в зависимости от *host* (или аргумента *family*, если он задан).300301Тип сокета будет [`SOCK_DGRAM`](https://python-all.ru/3.7/library/socket.html#socket.SOCK_DGRAM).302303*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).304305При успехе возвращается кортеж из `(transport, protocol)`.306307Остальные аргументы:308309- *local\_addr*, если задан, представляет собой кортеж `(local_host, local_port)`, используемый для привязки сокета локально. *local\_host* и *local\_port* разрешаются с помощью [`getaddrinfo()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo).310- *remote\_addr*, если задан, представляет собой кортеж `(remote_host, remote_port)`, используемый для подключения сокета к удалённому адресу. *remote\_host* и *remote\_port* разрешаются с помощью [`getaddrinfo()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo).311- *family*, *proto*, *flags* – необязательные семейство адресов, протокол и флаги, передаваемые в [`getaddrinfo()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo) для разрешения *host*. Если заданы, все они должны быть целыми числами из соответствующих констант модуля [`socket`](https://python-all.ru/3.7/library/socket.html#module-socket).312- *reuse\_port* указывает ядру разрешить привязку этой конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows и некоторых Unix-системах. Если константа `SO_REUSEPORT` не определена, то эта возможность не поддерживается.313- *allow\_broadcast* указывает ядру разрешить этой конечной точке отправлять сообщения на широковещательный адрес.314- *sock* может быть указан необязательно, чтобы использовать уже существующий, подключённый объект [`socket.socket`](https://python-all.ru/3.7/library/socket.html#socket.socket) для транспорта. Если указан, *local\_addr* и *remote\_addr* должны быть опущены (должны быть [`None`](https://python-all.ru/3.7/library/constants.html#None)).315316В Windows с [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) этот метод не поддерживается.317318См. примеры [протокол UDP-клиента эхо](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-udp-echo-client-protocol) и [протокол UDP-сервера эхо](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-udp-echo-server-protocol).319320Изменено в версии 3.4.4: Добавлены параметры *family*, *proto*, *flags*, *reuse\_address*, *reuse\_port, \*allow\_broadcast* и *sock*.321322Изменено в версии 3.7.6: Параметр *reuse\_address* больше не поддерживается по соображениям безопасности.323324#### `coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None)`325326Создать Unix-соединение.327328Семейство сокетов будет [`AF_UNIX`](https://python-all.ru/3.7/library/socket.html#socket.AF_UNIX); тип сокета будет [`SOCK_STREAM`](https://python-all.ru/3.7/library/socket.html#socket.SOCK_STREAM).329330При успехе возвращается кортеж из `(transport, protocol)`.331332*path* – это имя доменного сокета Unix, обязательный параметр, если не указан параметр *sock*. Поддерживаются абстрактные сокеты Unix, пути [`str`](https://python-all.ru/3.7/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.7/library/stdtypes.html#bytes) и [`Path`](https://python-all.ru/3.7/library/pathlib.html#pathlib.Path).333334Информацию об аргументах этого метода см. в документации метода [`loop.create_connection()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_connection).335336[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Unix.337338Новое в версии 3.7: параметр *ssl\_handshake\_timeout*.339340Изменено в версии 3.7: Параметр *path* теперь может быть [path-подобным объектом](https://python-all.ru/3.7/glossary.html#term-path-like-object).341342### [Создание сетевых серверов](https://python-all.ru/3.7/library/asyncio-eventloop.html#id6)343344#### `coroutine loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)`345346Создаёт TCP-сервер (тип сокета [`SOCK_STREAM`](https://python-all.ru/3.7/library/socket.html#socket.SOCK_STREAM)), прослушивающий порт на адресе *хоста*.347348Возвращает объект [`Server`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server).349350Аргументы:351352- *protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).353- Параметр *host* может принимать значения нескольких типов, которые определяют, где будет слушать сервер:354355 - Если *host* – строка, TCP-сервер привязывается к одному сетевому интерфейсу, указанному в *host*.356 - Если *host* – последовательность строк, TCP-сервер привязывается ко всем сетевым интерфейсам, указанным в этой последовательности.357 - Если *host* – пустая строка или `None`, подразумеваются все интерфейсы, и будет возвращён список из нескольких сокетов (скорее всего, один для IPv4 и один для IPv6).358- *family* может быть установлен в [`socket.AF_INET`](https://python-all.ru/3.7/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.7/library/socket.html#socket.AF_INET6), чтобы принудительно использовать IPv4 или IPv6. Если не задан, *family* будет определён по имени хоста (по умолчанию `AF_UNSPEC`).359- *flags* – битовая маска для [`getaddrinfo()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo).360- *sock* может быть указан опционально, чтобы использовать уже существующий объект сокета. Если он указан, *host* и *port* не должны быть заданы.361- *backlog* – максимальное количество соединений в очереди, передаваемое в [`listen()`](https://python-all.ru/3.7/library/socket.html#socket.socket.listen) (по умолчанию 100).362- *ssl* может быть установлен в экземпляр [`SSLContext`](https://python-all.ru/3.7/library/ssl.html#ssl.SSLContext) для включения TLS для принимаемых соединений.363- *reuse\_address* указывает ядру повторно использовать локальный сокет в состоянии `TIME_WAIT`, не дожидаясь истечения его естественного тайм-аута. Если не указан, автоматически устанавливается в `True` на Unix.364- *reuse\_port* указывает ядру разрешить привязку этой конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows.365- *ssl\_handshake\_timeout* (для TLS-сервера) – время ожидания в секундах завершения TLS-рукопожатия перед разрывом соединения. `60.0` секунд, если `None` (по умолчанию).366- *start\_serving*, установленный в `True` (по умолчанию), заставляет созданный сервер немедленно начать принимать соединения. Если установлен в `False`, пользователь должен дождаться [`Server.start_serving()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server.start_serving) или [`Server.serve_forever()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server.serve_forever), чтобы сервер начал принимать соединения.367368Новое в версии 3.7: Добавлены параметры *ssl\_handshake\_timeout* и *start\_serving*.369370Изменено в версии 3.6: Параметр сокета `TCP_NODELAY` теперь устанавливается по умолчанию для всех TCP-соединений.371372Изменено в версии 3.5: Добавлена поддержка SSL/TLS в [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).373374Изменено в версии 3.5.1: Параметр *host* может быть последовательностью строк.375376> **См. также**377>378> Функция [`start_server()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.start_server) – это API более высокого уровня, который возвращает пару [`StreamReader`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.StreamReader) и [`StreamWriter`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.StreamWriter), которые можно использовать в коде с async/await.379380#### `coroutine loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)`381382Аналогично [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server), но работает с семейством сокетов [`AF_UNIX`](https://python-all.ru/3.7/library/socket.html#socket.AF_UNIX).383384*path* – имя сокета домена Unix и является обязательным, если не передан аргумент *sock*. Поддерживаются абстрактные сокеты Unix, пути [`str`](https://python-all.ru/3.7/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.7/library/stdtypes.html#bytes) и [`Path`](https://python-all.ru/3.7/library/pathlib.html#pathlib.Path).385386Информацию об аргументах этого метода см. в документации метода [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server).387388[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Unix.389390Новое в версии 3.7: параметры *ssl\_handshake\_timeout* и *start\_serving*.391392Изменено в версии 3.7: параметр *path* теперь может быть объектом [`Path`](https://python-all.ru/3.7/library/pathlib.html#pathlib.Path).393394#### `coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None)`395396Оборачивает уже принятое соединение в пару транспорт/протокол.397398Этот метод могут использовать серверы, которые принимают соединения вне asyncio, но используют asyncio для их обработки.399400Параметры:401402- *protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).403- *sock* – это существующий объект сокета, возвращённый из [`socket.accept`](https://python-all.ru/3.7/library/socket.html#socket.socket.accept).404- *ssl* можно установить в [`SSLContext`](https://python-all.ru/3.7/library/ssl.html#ssl.SSLContext), чтобы включить SSL для принятых соединений.405- *ssl\_handshake\_timeout* (для SSL-соединения) – время в секундах ожидания завершения SSL-рукопожатия перед разрывом соединения. `60.0` секунд, если `None` (по умолчанию).406407Возвращает пару `(transport, protocol)`.408409Новое в версии 3.7: параметр *ssl\_handshake\_timeout*.410411Новое в версии 3.5.3.412413### [Передача файлов](https://python-all.ru/3.7/library/asyncio-eventloop.html#id7)414415#### `coroutine loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)`416417Отправляет *файл* через *транспорт*. Возвращает общее количество отправленных байтов.418419Метод использует высокопроизводительный [`os.sendfile()`](https://python-all.ru/3.7/library/os.html#os.sendfile), если доступен.420421*file* должен быть обычным файловым объектом, открытым в бинарном режиме.422423*offset* указывает, с какого места начинать чтение файла. Если задан, *count* – это общее количество байтов для передачи, в отличие от отправки файла до достижения EOF. Позиция в файле всегда обновляется, даже если этот метод вызывает ошибку, а [`file.tell()`](https://python-all.ru/3.7/library/io.html#io.IOBase.tell) можно использовать для получения фактического количества отправленных байтов.424425*fallback*, установленный в `True`, заставляет asyncio вручную читать и отправлять файл, если платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет в Unix).426427Вызывает [`SendfileNotAvailableError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.SendfileNotAvailableError), если система не поддерживает системный вызов *sendfile*, а *fallback* равен `False`.428429Добавлено в версии 3.7.430431### [Обновление TLS](https://python-all.ru/3.7/library/asyncio-eventloop.html#id8)432433#### `coroutine loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None)`434435Обновляет существующее соединение на основе транспорта до TLS.436437Возвращает новый экземпляр транспорта, который *протокол* должен начать использовать сразу после *await*. Экземпляр *транспорт*, переданный методу *start\_tls*, больше не следует использовать.438439Параметры:440441- *транспорт* и *протокол* – экземпляры, возвращаемые методами наподобие [`create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server) и [`create_connection()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_connection).442- *sslcontext*: настроенный экземпляр [`SSLContext`](https://python-all.ru/3.7/library/ssl.html#ssl.SSLContext).443- *server\_side* передавайте `True` при обновлении серверного соединения (например, созданного [`create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server)).444- *server\_hostname*: задаёт или переопределяет имя узла, с которым будет сверяться сертификат целевого сервера.445- *ssl\_handshake\_timeout* – время в секундах, в течение которого ожидается завершение TLS-рукопожатия перед разрывом соединения (для TLS-соединений). `60.0` секунд, если `None` (по умолчанию).446447Добавлено в версии 3.7.448449### [Наблюдение за файловыми дескрипторами](https://python-all.ru/3.7/library/asyncio-eventloop.html#id9)450451#### `loop.add_reader(fd, callback, *args)`452453Начинает наблюдение за файловым дескриптором *fd* на готовность к чтению и вызывает *колбэк* с указанными аргументами, как только *fd* станет доступен для чтения.454455#### `loop.remove_reader(fd)`456457Останавливает мониторинг файлового дескриптора *fd* на доступность чтения.458459#### `loop.add_writer(fd, callback, *args)`460461Начинает отслеживать готовность файлового дескриптора *fd* к записи и вызывает *колбэк* с указанными аргументами, как только *fd* становится доступным для записи.462463Используйте [`functools.partial()`](https://python-all.ru/3.7/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio-pass-keywords) в *колбэк*.464465#### `loop.remove_writer(fd)`466467Останавливает мониторинг файлового дескриптора *fd* на доступность записи.468469См. также раздел [Поддержка платформ](https://python-all.ru/3.7/library/asyncio-platforms.html#asyncio-platform-support) о некоторых ограничениях этих методов.470471### [Работа с объектами сокетов напрямую](https://python-all.ru/3.7/library/asyncio-eventloop.html#id10)472473В целом реализации протоколов, использующие API на основе транспорта, такие как [`loop.create_connection()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_connection) и [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server), работают быстрее реализаций, работающих напрямую с сокетами. Однако есть случаи, когда производительность не критична, и работать напрямую с объектами [`socket`](https://python-all.ru/3.7/library/socket.html#socket.socket) удобнее.474475#### `coroutine loop.sock_recv(sock, nbytes)`476477Получает до *nbytes* байт из *sock*. Асинхронная версия [`socket.recv()`](https://python-all.ru/3.7/library/socket.html#socket.socket.recv).478479Возвращает полученные данные в виде объекта bytes.480481*sock* должен быть неблокирующим сокетом.482483Изменено в версии 3.7: Хотя этот метод всегда документировался как корутинный, до Python 3.7 он возвращал [`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7 это `async def` метод.484485#### `coroutine loop.sock_recv_into(sock, buf)`486487Получает данные из *sock* в буфер *buf*. По аналогии с блокирующим методом [`socket.recv_into()`](https://python-all.ru/3.7/library/socket.html#socket.socket.recv_into).488489Возвращает количество байт, записанных в буфер.490491*sock* должен быть неблокирующим сокетом.492493Добавлено в версии 3.7.494495#### `coroutine loop.sock_sendall(sock, data)`496497Отправляет *data* в сокет *sock*. Асинхронная версия [`socket.sendall()`](https://python-all.ru/3.7/library/socket.html#socket.socket.sendall).498499Этот метод продолжает отправку в сокет, пока не будут отправлены все данные из *data* или не возникнет ошибка. В случае успеха возвращается `None`. При ошибке вызывается исключение. Кроме того, невозможно определить, какой объём данных (если он был) был успешно обработан принимающей стороной соединения.500501*sock* должен быть неблокирующим сокетом.502503Изменено в версии 3.7: Хотя метод всегда документировался как корутинный метод, до Python 3.7 он возвращал [`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7, это метод `async def`.504505#### `coroutine loop.sock_connect(sock, address)`506507Подключает *sock* к удалённому сокету по адресу *address*.508509Асинхронная версия [`socket.connect()`](https://python-all.ru/3.7/library/socket.html#socket.socket.connect).510511*sock* должен быть неблокирующим сокетом.512513Изменено в версии 3.5.2: `address` больше не требует разрешения. `sock_connect` попытается проверить, разрешён ли уже *address*, вызвав [`socket.inet_pton()`](https://python-all.ru/3.7/library/socket.html#socket.inet_pton). Если нет, [`loop.getaddrinfo()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo) будет использован для разрешения *address*.514515> **См. также**516>517> [`loop.create_connection()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_connection) и [`asyncio.open_connection()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.open_connection).518519#### `coroutine loop.sock_accept(sock)`520521Принимает соединение. Смоделирован по аналогии с блокирующим методом [`socket.accept()`](https://python-all.ru/3.7/library/socket.html#socket.socket.accept).522523Сокет должен быть привязан к адресу и ожидать подключения. Возвращаемое значение – пара `(conn, address)`, где *conn* – это *новый* объект сокета, пригодный для отправки и получения данных по соединению, а *address* – адрес, привязанный к сокету на другом конце соединения.524525*sock* должен быть неблокирующим сокетом.526527Изменено в версии 3.7: Хотя этот метод всегда документировался как корутинный метод, до Python 3.7 он возвращал [`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7, это `async def` метод.528529> **См. также**530>531> [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server) и [`start_server()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.start_server).532533#### `coroutine loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)`534535Отправляет файл с использованием высокопроизводительного [`os.sendfile`](https://python-all.ru/3.7/library/os.html#os.sendfile), если возможно. Возвращает общее количество отправленных байт.536537Асинхронная версия [`socket.sendfile()`](https://python-all.ru/3.7/library/socket.html#socket.socket.sendfile).538539*sock* должен быть неблокирующим [`socket.SOCK_STREAM`](https://python-all.ru/3.7/library/socket.html#socket.SOCK_STREAM) [`socket`](https://python-all.ru/3.7/library/socket.html#socket.socket).540541*file* должен быть обычным файловым объектом, открытым в бинарном режиме.542543*offset* указывает, с какого места начинать чтение файла. Если задан, *count* – это общее количество байтов для передачи, в отличие от отправки файла до достижения EOF. Позиция в файле всегда обновляется, даже если этот метод вызывает ошибку, а [`file.tell()`](https://python-all.ru/3.7/library/io.html#io.IOBase.tell) можно использовать для получения фактического количества отправленных байтов.544545*fallback*, если установлено в `True`, заставляет asyncio вручную читать и отправлять файл, когда платформа не поддерживает системный вызов sendfile (например, Windows или SSL-сокет в Unix).546547Вызывает [`SendfileNotAvailableError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.SendfileNotAvailableError), если система не поддерживает системный вызов *sendfile* и *fallback* равен `False`.548549*sock* должен быть неблокирующим сокетом.550551Добавлено в версии 3.7.552553### [DNS](https://python-all.ru/3.7/library/asyncio-eventloop.html#id11)554555#### `coroutine loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)`556557Асинхронная версия [`socket.getaddrinfo()`](https://python-all.ru/3.7/library/socket.html#socket.getaddrinfo).558559#### `coroutine loop.getnameinfo(sockaddr, flags=0)`560561Асинхронная версия [`socket.getnameinfo()`](https://python-all.ru/3.7/library/socket.html#socket.getnameinfo).562563Изменено в версии 3.7: Оба метода, *getaddrinfo* и *getnameinfo*, всегда документировались как возвращающие корутину, но до Python 3.7 на самом деле возвращали объекты [`asyncio.Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future). Начиная с Python 3.7 оба метода являются корутинами.564565### [Работа с каналами](https://python-all.ru/3.7/library/asyncio-eventloop.html#id12)566567#### `coroutine loop.connect_read_pipe(protocol_factory, pipe)`568569Регистрирует читающий конец канала *pipe* в цикле событий.570571*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола asyncio](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).572573*pipe* – это [объект, подобный файлу](https://python-all.ru/3.7/glossary.html#term-file-object).574575Возвращает пару `(transport, protocol)`, где *транспорт* поддерживает интерфейс [`ReadTransport`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.ReadTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.576577При [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) цикле событий канал *pipe* переводится в неблокирующий режим.578579#### `coroutine loop.connect_write_pipe(protocol_factory, pipe)`580581Регистрирует записывающий конец канала *pipe* в цикле событий.582583*protocol\_factory* должен быть вызываемым объектом, возвращающим реализацию [протокола asyncio](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol).584585*pipe* – это [объект, подобный файлу](https://python-all.ru/3.7/glossary.html#term-file-object).586587Возвращает пару `(transport, protocol)`, где *транспорт* поддерживает интерфейс [`WriteTransport`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.WriteTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.588589При [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) цикле событий канал *pipe* переводится в неблокирующий режим.590591> **Примечание**592>593> [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) не поддерживает указанные выше методы в Windows. Используйте [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) вместо них в Windows.594595> **См. также**596>597> Методы [`loop.subprocess_exec()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec) и [`loop.subprocess_shell()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.subprocess_shell).598599### [Сигналы Unix](https://python-all.ru/3.7/library/asyncio-eventloop.html#id13)600601#### `loop.add_signal_handler(signum, callback, *args)`602603Устанавливает *колбэк* в качестве обработчика сигнала *signum*.604605Колбэк будет вызван *loop* вместе с другими поставленными в очередь колбэками и готовыми к запуску корутинами этого цикла событий. В отличие от обработчиков сигналов, зарегистрированных с помощью [`signal.signal()`](https://python-all.ru/3.7/library/signal.html#signal.signal), колбэк, зарегистрированный этой функцией, может взаимодействовать с циклом событий.606607Вызывает [`ValueError`](https://python-all.ru/3.7/library/exceptions.html#ValueError), если номер сигнала недопустим или его невозможно перехватить. Вызывает [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError), если возникла проблема при установке обработчика.608609Используйте [`functools.partial()`](https://python-all.ru/3.7/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio-pass-keywords) в *колбэк*.610611Как и [`signal.signal()`](https://python-all.ru/3.7/library/signal.html#signal.signal), эта функция должна вызываться в главном потоке.612613#### `loop.remove_signal_handler(sig)`614615Удаляет обработчик сигнала *sig*.616617Возвращает `True`, если обработчик сигнала был удалён, или `False`, если для указанного сигнала обработчик не был установлен.618619[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Unix.620621> **См. также**622>623> Модуль [`signal`](https://python-all.ru/3.7/library/signal.html#module-signal).624625### [Выполнение кода в пулах потоков или процессов](https://python-all.ru/3.7/library/asyncio-eventloop.html#id14)626627#### `awaitable loop.run_in_executor(executor, func, *args)`628629Планирует вызов *func* в указанном исполнителе.630631Аргумент *исполнитель* должен быть экземпляром [`concurrent.futures.Executor`](https://python-all.ru/3.7/library/concurrent.futures.html#concurrent.futures.Executor) Исполнитель по умолчанию используется, если *исполнитель* равен `None`.632633Пример:634635```python636import asyncio637import concurrent.futures638639def blocking_io():640 # Файловые операции (например, логирование) могут блокировать цикл событий: выполняйте их в пуле потоков.641 # цикл событий: выполняйте их в пуле потоков.642 with open('/dev/urandom', 'rb') as f:643 return f.read(100)644645def cpu_bound():646 # CPU-ёмкие операции заблокируют цикл событий:647 # в целом предпочтительнее выполнять их в648 # пуле процессов.649 return sum(i * i for i in range(10 ** 7))650651async def main():652 loop = asyncio.get_running_loop()653654 ## Варианты:655656 # 1. Запуск в исполнителе цикла по умолчанию:657 result = await loop.run_in_executor(658 None, blocking_io)659 print('default thread pool', result)660661 # 2. Запуск в пользовательском пуле потоков:662 with concurrent.futures.ThreadPoolExecutor() as pool:663 result = await loop.run_in_executor(664 pool, blocking_io)665 print('custom thread pool', result)666667 # 3. Запуск в пользовательском пуле процессов:668 with concurrent.futures.ProcessPoolExecutor() as pool:669 result = await loop.run_in_executor(670 pool, cpu_bound)671 print('custom process pool', result)672673asyncio.run(main())674```675676Этот метод возвращает объект [`asyncio.Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future).677678Используйте [`functools.partial()`](https://python-all.ru/3.7/library/functools.html#functools.partial) [для передачи именованных аргументов](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio-pass-keywords) в *func*.679680Изменено в версии 3.5.3: [`loop.run_in_executor()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_in_executor) больше не настраивает `max_workers` создаваемого исполнителя пула потоков, оставляя настройку по умолчанию самому исполнителю пула потоков ([`ThreadPoolExecutor`](https://python-all.ru/3.7/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor)).681682#### `loop.set_default_executor(executor)`683684Установить *исполнитель* в качестве исполнителя по умолчанию, используемого [`run_in_executor()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_in_executor). *Исполнитель* должен быть экземпляром [`ThreadPoolExecutor`](https://python-all.ru/3.7/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor).685686Устарело с версии 3.7: Использование исполнителя, не являющегося экземпляром [`ThreadPoolExecutor`](https://python-all.ru/3.7/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor), устарело и приведёт к ошибке в Python 3.9.687688*Исполнитель* должен быть экземпляром [`concurrent.futures.ThreadPoolExecutor`](https://python-all.ru/3.7/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor).689690### [API обработки ошибок](https://python-all.ru/3.7/library/asyncio-eventloop.html#id15)691692Позволяет настраивать обработку исключений в цикле событий.693694#### `loop.set_exception_handler(handler)`695696Устанавливает *handler* в качестве нового обработчика исключений цикла событий.697698Если *handler* равен `None`, будет установлен обработчик исключений по умолчанию. В противном случае *handler* должен быть вызываемым объектом с сигнатурой, соответствующей `(loop, context)`, где `loop` – это ссылка на активный цикл событий, а `context` – это объект `dict`, содержащий сведения об исключении (см. документацию [`call_exception_handler()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_exception_handler) для подробностей о контексте).699700#### `loop.get_exception_handler()`701702Возвращает текущий обработчик исключений или `None`, если не был установлен пользовательский обработчик.703704Новое в версии 3.5.2.705706#### `loop.default_exception_handler(context)`707708Обработчик исключений по умолчанию.709710Вызывается при возникновении исключения, если не установлен никакой обработчик. Может быть вызван пользовательским обработчиком, который хочет передать управление поведению по умолчанию.711712Параметр *context* имеет то же значение, что и в [`call_exception_handler()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_exception_handler).713714#### `loop.call_exception_handler(context)`715716Вызывает обработчик исключений текущего цикла событий.717718*context* – это объект `dict`, содержащий следующие ключи (в будущих версиях Python могут появиться новые ключи):719720- ‘message’: сообщение об ошибке;721- 'исключение' (необязательно): объект исключения;722- ‘future’ (необязательно): экземпляр [`asyncio.Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future);723- ‘handle’ (необязательно): экземпляр [`asyncio.Handle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Handle);724- 'протокол' (необязательно): экземпляр [Protocol](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-protocol);725- 'транспорт' (необязательно): экземпляр [Transport](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-transport);726- ‘socket’ (необязательно): экземпляр [`socket.socket`](https://python-all.ru/3.7/library/socket.html#socket.socket).727728> **Примечание**729>730> Этот метод не следует переопределять в подклассах циклов событий. Для настраиваемой обработки исключений используйте метод [`set_exception_handler()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.set_exception_handler).731732### [Включение режима отладки](https://python-all.ru/3.7/library/asyncio-eventloop.html#id16)733734#### `loop.get_debug()`735736Возвращает режим отладки ([`bool`](https://python-all.ru/3.7/library/functions.html#bool)) цикла событий.737738Значение по умолчанию – `True`, если переменная окружения [`PYTHONASYNCIODEBUG`](https://python-all.ru/3.7/using/cmdline.html#envvar-PYTHONASYNCIODEBUG) имеет непустое строковое значение, и `False` в противном случае.739740#### `loop.set_debug(enabled: bool)`741742Устанавливает режим отладки цикла событий.743744Изменено в версии 3.7: Новый параметр командной строки `-X dev` теперь также можно использовать для включения режима отладки.745746> **См. также**747>748> [Режим отладки asyncio](https://python-all.ru/3.7/library/asyncio-dev.html#asyncio-debug-mode).749750### [Запуск подпроцессов](https://python-all.ru/3.7/library/asyncio-eventloop.html#id17)751752Методы, описанные в этом подразделе, являются низкоуровневыми. В обычном коде с async/await рекомендуется вместо них использовать высокоуровневые удобные функции [`asyncio.create_subprocess_shell()`](https://python-all.ru/3.7/library/asyncio-subprocess.html#asyncio.create_subprocess_shell) и [`asyncio.create_subprocess_exec()`](https://python-all.ru/3.7/library/asyncio-subprocess.html#asyncio.create_subprocess_exec).753754> **Примечание**755>756> Цикл событий asyncio по умолчанию на **Windows** не поддерживает подпроцессы. Подробнее см. [Поддержка подпроцессов в Windows](https://python-all.ru/3.7/library/asyncio-platforms.html#asyncio-windows-subprocess).757758#### `coroutine loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)`759760Создаёт подпроцесс из одного или нескольких строковых аргументов, заданных параметром *args*.761762Параметр *args* должен быть списком строк, представленным следующим образом:763764- [`str`](https://python-all.ru/3.7/library/stdtypes.html#str);765- или [`bytes`](https://python-all.ru/3.7/library/stdtypes.html#bytes), закодированная в [кодировку файловой системы](https://python-all.ru/3.7/library/os.html#filesystem-encoding).766767Первая строка указывает исполняемый файл программы, а остальные строки задают аргументы. Вместе строковые аргументы образуют `argv` программы.768769Это похоже на класс [`subprocess.Popen`](https://python-all.ru/3.7/library/subprocess.html#subprocess.Popen) из стандартной библиотеки, который вызывается с `shell=False` и списком строк, передаваемых в качестве первого аргумента; однако, если [`Popen`](https://python-all.ru/3.7/library/subprocess.html#subprocess.Popen) принимает один аргумент – список строк, *subprocess\_exec* принимает несколько строковых аргументов.770771Параметр *protocol\_factory* должен быть вызываемым объектом, возвращающим подкласс класса [`asyncio.SubprocessProtocol`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.SubprocessProtocol).772773Другие параметры:774775- *stdin*: либо объект, подобный файлу, представляющий канал, который будет подключён к стандартному потоку ввода подпроцесса с помощью [`connect_write_pipe()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.connect_write_pipe), либо константа [`subprocess.PIPE`](https://python-all.ru/3.7/library/subprocess.html#subprocess.PIPE) (по умолчанию). По умолчанию создаётся и подключается новый канал.776- *stdout*: либо объект, подобный файлу, представляющий канал, который будет подключён к стандартному потоку вывода подпроцесса с помощью [`connect_read_pipe()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.connect_read_pipe), либо константа [`subprocess.PIPE`](https://python-all.ru/3.7/library/subprocess.html#subprocess.PIPE) (по умолчанию). По умолчанию создаётся и подключается новый канал.777- *stderr*: либо объект, подобный файлу, представляющий канал, который будет подключён к стандартному потоку ошибок подпроцесса с помощью [`connect_read_pipe()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.connect_read_pipe), либо одна из констант [`subprocess.PIPE`](https://python-all.ru/3.7/library/subprocess.html#subprocess.PIPE) (по умолчанию) или [`subprocess.STDOUT`](https://python-all.ru/3.7/library/subprocess.html#subprocess.STDOUT).778779 По умолчанию создаётся и подключается новый канал. Если указано [`subprocess.STDOUT`](https://python-all.ru/3.7/library/subprocess.html#subprocess.STDOUT), стандартный поток ошибок подпроцесса будет подключён к тому же каналу, что и стандартный поток вывода.780- Все остальные именованные аргументы передаются в [`subprocess.Popen`](https://python-all.ru/3.7/library/subprocess.html#subprocess.Popen) без интерпретации, за исключением *bufsize*, *universal\_newlines* и *shell*, которые не должны указываться вовсе.781782Описание остальных аргументов см. в конструкторе класса [`subprocess.Popen`](https://python-all.ru/3.7/library/subprocess.html#subprocess.Popen).783784Возвращает пару из `(transport, protocol)`, где *транспорт* соответствует базовому классу [`asyncio.SubprocessTransport`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.SubprocessTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.785786#### `coroutine loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)`787788Создаёт подпроцесс из *cmd*, который может быть строкой [`str`](https://python-all.ru/3.7/library/stdtypes.html#str) или [`bytes`](https://python-all.ru/3.7/library/stdtypes.html#bytes), закодированной в [кодировку файловой системы](https://python-all.ru/3.7/library/os.html#filesystem-encoding), используя синтаксис командной оболочки платформы («shell»).789790Это похоже на [`subprocess.Popen`](https://python-all.ru/3.7/library/subprocess.html#subprocess.Popen) класс из стандартной библиотеки, вызываемый с помощью `shell=True`.791792Параметр *protocol\_factory* должен быть вызываемым объектом, возвращающим подкласс класса [`SubprocessProtocol`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.SubprocessProtocol).793794Подробнее об остальных аргументах см. в [`subprocess_exec()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec).795796Возвращает пару из `(transport, protocol)`, где *транспорт* соответствует базовому классу [`SubprocessTransport`](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio.SubprocessTransport), а *протокол* – объект, созданный фабрикой *protocol\_factory*.797798> **Примечание**799>800> Ответственность за то, чтобы все пробельные и специальные символы были правильно экранированы, лежит на приложении – это позволяет избежать уязвимостей [инъекции команд оболочки](https://python-all.ru/3.7/library/asyncio-eventloop.html). Для корректного экранирования пробелов и спецсимволов в строках, используемых при построении команд оболочки, можно применить функцию [`shlex.quote()`](https://python-all.ru/3.7/library/shlex.html#shlex.quote).801802## Дескрипторы колбэков803804#### `class asyncio.Handle`805806Объект-обёртка колбэка, возвращаемый [`loop.call_soon()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_soon), [`loop.call_soon_threadsafe()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe).807808#### `cancel()`809810Отменяет колбэк. Если колбэк уже был отменён или выполнен, этот метод не делает ничего.811812#### `cancelled()`813814Возвращает `True`, если колбэк был отменён.815816Добавлено в версии 3.7.817818#### `class asyncio.TimerHandle`819820Объект-обёртка колбэка, возвращаемый [`loop.call_later()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_later) и [`loop.call_at()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_at).821822Этот класс является подклассом [`Handle`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Handle).823824#### `when()`825826Возвращает запланированное время выполнения колбэка в секундах [`float`](https://python-all.ru/3.7/library/functions.html#float).827828Время – абсолютная временная метка, использующая ту же систему отсчёта, что и [`loop.time()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.time).829830Добавлено в версии 3.7.831832## Объекты сервера833834Объекты сервера создаются функциями [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server), [`loop.create_unix_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_unix_server), [`start_server()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.start_server) и [`start_unix_server()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.start_unix_server).835836Не создавайте экземпляр класса напрямую.837838#### `class asyncio.Server`839840Объекты *Server* являются асинхронными контекстными менеджерами. При использовании в операторе `async with` гарантируется, что объект Server будет закрыт и не будет принимать новые подключения после завершения оператора `async with`:841842```python843srv = await loop.create_server(...)844845async with srv:846 # некоторый код847848# На данный момент srv закрыт и больше не принимает новые соединения.849```850851Изменено в версии 3.7: Объект Server является асинхронным контекстным менеджером начиная с Python 3.7.852853#### `close()`854855Прекращает обслуживание: закрывает слушающие сокеты и устанавливает атрибут [`sockets`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server.sockets) в `None`.856857Сокеты, представляющие существующие входящие клиентские подключения, остаются открытыми.858859Сервер закрывается асинхронно, используйте [`wait_closed()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server.wait_closed)\\nкорутину, чтобы дождаться закрытия сервера.860861#### `get_loop()`862863Возвращает цикл событий, связанный с объектом сервера.864865Добавлено в версии 3.7.866867#### `coroutine start_serving()`868869Начинает принимать соединения.870871Этот метод идемпотентен, поэтому его можно вызывать, когда сервер уже обслуживает.872873Параметр *start\_serving*, передаваемый только по ключевому слову, в [`loop.create_server()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_server) и [`asyncio.start_server()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.start_server) позволяет создать объект Server, который изначально не принимает соединения. В этом случае можно использовать `Server.start_serving()` или [`Server.serve_forever()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server.serve_forever), чтобы заставить Server начать принимать соединения.874875Добавлено в версии 3.7.876877#### `coroutine serve_forever()`878879Начинает принимать соединения до отмены корутины. Отмена задачи `serve_forever` приводит к закрытию сервера.880881Этот метод можно вызывать, если сервер уже принимает соединения. Для одного объекта *Server* может существовать только одна задача `serve_forever`.882883Пример:884885```python886async def client_connected(reader, writer):887 # Общение с клиентом через888 # потоки чтения/записи. Например:889 await reader.readline()890891async def main(host, port):892 srv = await asyncio.start_server(893 client_connected, host, port)894 await srv.serve_forever()895896asyncio.run(main('127.0.0.1', 0))897```898899Добавлено в версии 3.7.900901#### `is_serving()`902903Возвращает `True`, если сервер принимает новые соединения.904905Добавлено в версии 3.7.906907#### `coroutine wait_closed()`908909Ожидайте завершения метода [`close()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.Server.close).910911#### `sockets`912913Список объектов [`socket.socket`](https://python-all.ru/3.7/library/socket.html#socket.socket), на которых сервер прослушивает, или `None`, если сервер закрыт.914915Изменено в версии 3.7: До Python 3.7 `Server.sockets` возвращал внутренний список серверных сокетов напрямую. В версии 3.7 возвращается копия этого списка.916917## Реализации цикла событий918919asyncio поставляется с двумя различными реализациями цикла событий: [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) и [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop).920921По умолчанию asyncio настроен на использование [`SelectorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.SelectorEventLoop) на всех платформах.922923#### `class asyncio.SelectorEventLoop`924925Цикл событий на основе модуля [`selectors`](https://python-all.ru/3.7/library/selectors.html#module-selectors).926927Использует наиболее эффективный *селектор*, доступный для данной платформы. Также можно вручную настроить конкретную реализацию селектора:928929```python930import asyncio931import selectors932933selector = selectors.SelectSelector()934loop = asyncio.SelectorEventLoop(selector)935asyncio.set_event_loop(loop)936```937938[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Unix, Windows.939940#### `class asyncio.ProactorEventLoop`941942Цикл событий для Windows, использующий «порты завершения ввода-вывода» (IOCP).943944[Доступность](https://python-all.ru/3.7/library/intro.html#availability): Windows.945946Пример использования [`ProactorEventLoop`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.ProactorEventLoop) в Windows:947948```python949import asyncio950import sys951952if sys.platform == 'win32':953 loop = asyncio.ProactorEventLoop()954 asyncio.set_event_loop(loop)955```956957> **См. также**958>959> [документация MSDN по портам завершения ввода-вывода](https://python-all.ru/3.7/library/asyncio-eventloop.html).960961#### `class asyncio.AbstractEventLoop`962963Абстрактный базовый класс для циклов событий, совместимых с asyncio.964965Раздел [Методы цикла событий](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio-event-loop) перечисляет все методы, которые должна определять альтернативная реализация `AbstractEventLoop` .966967## Примеры968969Обратите внимание, что все примеры в этом разделе **намеренно** показывают, как использовать низкоуровневые API цикла событий, такие как [`loop.run_forever()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_forever) и [`loop.call_soon()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_soon). Современные приложения asyncio редко требуют такого стиля написания; рекомендуется использовать высокоуровневые функции, такие как [`asyncio.run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run).970971### Hello World с call\_soon()972973Пример использования метода [`loop.call_soon()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_soon) для планирования колбэка. Колбэк выводит `"Hello World"`, а затем останавливает цикл событий:974975```python976import asyncio977978def hello_world(loop):979 """Колбэк для вывода 'Hello World' и остановки цикла событий"""980 print('Hello World')981 loop.stop()982983loop = asyncio.get_event_loop()984985# Запланировать вызов hello_world()986loop.call_soon(hello_world, loop)987988# Блокирующий вызов прерван loop.stop()989try:990 loop.run_forever()991finally:992 loop.close()993```994995> **См. также**996>997> Аналогичный [пример Hello World](https://python-all.ru/3.7/library/asyncio-task.html#coroutine), созданный с помощью корутины и функции [`run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run).998999### Отображение текущей даты с помощью call\_later()10001001Пример колбэка, выводящего текущую дату каждую секунду. Колбэк использует метод [`loop.call_later()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.call_later) для повторного планирования самого себя через 5 секунд, а затем останавливает цикл событий:10021003```python1004import asyncio1005import datetime10061007def display_date(end_time, loop):1008 print(datetime.datetime.now())1009 if (loop.time() + 1.0) < end_time:1010 loop.call_later(1, display_date, end_time, loop)1011 else:1012 loop.stop()10131014loop = asyncio.get_event_loop()10151016# Запланировать первый вызов display_date()1017end_time = loop.time() + 5.01018loop.call_soon(display_date, end_time, loop)10191020# Блокирующий вызов прерван loop.stop()1021try:1022 loop.run_forever()1023finally:1024 loop.close()1025```10261027> **См. также**1028>1029> Аналогичный [пример с текущей датой](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-example-sleep), созданный с помощью корутины и функции [`run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run).10301031### Наблюдение за файловым дескриптором на события чтения10321033Ожидание, пока файловый дескриптор не получит некоторые данные, с помощью метода [`loop.add_reader()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.add_reader), после чего цикл событий закрывается:10341035```python1036import asyncio1037from socket import socketpair10381039# Создать пару связанных файловых дескрипторов1040rsock, wsock = socketpair()10411042loop = asyncio.get_event_loop()10431044def reader():1045 data = rsock.recv(100)1046 print("Received:", data.decode())10471048 # Готово: отменить регистрацию файлового дескриптора1049 loop.remove_reader(rsock)10501051 # Остановить цикл событий1052 loop.stop()10531054# Зарегистрировать файловый дескриптор для события чтения1055loop.add_reader(rsock, reader)10561057# Симулировать приём данных из сети1058loop.call_soon(wsock.send, 'abc'.encode())10591060try:1061 # Запустить цикл событий1062 loop.run_forever()1063finally:1064 # Готово. Закрыть сокеты и цикл событий.1065 rsock.close()1066 wsock.close()1067 loop.close()1068```10691070> **См. также**1071>1072> - Аналогичный [пример](https://python-all.ru/3.7/library/asyncio-protocol.html#asyncio-example-create-connection) с использованием транспортов, протоколов и метода [`loop.create_connection()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_connection).1073> - Ещё один аналогичный [пример](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio-example-create-connection-streams) с использованием высокоуровневой функции [`asyncio.open_connection()`](https://python-all.ru/3.7/library/asyncio-stream.html#asyncio.open_connection) и потоков данных.10741075### Установка обработчиков сигналов SIGINT и SIGTERM10761077(Этот `signals` пример работает только на Unix.)10781079Регистрация обработчиков для сигналов `SIGINT` и `SIGTERM` с помощью метода [`loop.add_signal_handler()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.add_signal_handler):10801081```python1082import asyncio1083import functools1084import os1085import signal10861087def ask_exit(signame, loop):1088 print("got signal %s: exit" % signame)1089 loop.stop()10901091async def main():1092 loop = asyncio.get_running_loop()10931094 for signame in {'SIGINT', 'SIGTERM'}:1095 loop.add_signal_handler(1096 getattr(signal, signame),1097 functools.partial(ask_exit, signame, loop))10981099 await asyncio.sleep(3600)11001101print("Event loop running for 1 hour, press Ctrl+C to interrupt.")1102print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")11031104asyncio.run(main())1105```1106