asyncio-eventloop.md
1> **Источник:** https://python-all.ru/3.6/library/asyncio-eventloop.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.5.1. Базовый цикл событий89**Исходный код:** [Lib/asyncio/events.py](https://python-all.ru/src/3.6/Lib/asyncio/events.py)1011Цикл событий – это центральное исполнительное устройство, предоставляемое модулем [`asyncio`](https://python-all.ru/3.6/library/asyncio.html#module-asyncio). Он предоставляет множество возможностей, в том числе:1213- Регистрация, выполнение и отмена отложенных вызовов (тайм-аутов).14- Создание [транспортов](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-transport) клиента и сервера для различных видов взаимодействия.15- Запуск подпроцессов и связанных с ними [транспортов](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-transport) для взаимодействия с внешней программой.16- Делегирование дорогостоящих вызовов функций пулу потоков.1718#### `class asyncio.BaseEventLoop`1920Этот класс является деталью реализации. Он является подклассом [`AbstractEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop) и может быть базовым классом конкретных реализаций цикла событий, находящихся в [`asyncio`](https://python-all.ru/3.6/library/asyncio.html#module-asyncio). Его не следует использовать напрямую; вместо этого используйте [`AbstractEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop). `BaseEventLoop` не должен наследоваться сторонним кодом; внутренний интерфейс нестабилен.2122#### `class asyncio.AbstractEventLoop`2324Абстрактный базовый класс циклов событий.2526This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).2728## 18.5.1.1. Запуск цикла событий2930#### `AbstractEventLoop.run_forever()`3132Выполняется до вызова [`stop()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.stop). Если [`stop()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.stop) вызывается до вызова [`run_forever()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_forever), то однократно опрашивается I/O-селектор с нулевым тайм-аутом, выполняются все колбэки, запланированные в ответ на I/O-события (а также уже запланированные), после чего происходит выход. Если [`stop()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.stop) вызывается во время выполнения [`run_forever()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_forever), то будет выполнен текущий набор колбэков, после чего произойдёт выход. Обратите внимание, что колбэки, запланированные другими колбэками, в этом случае не выполнятся; они выполнятся при следующем вызове [`run_forever()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_forever).3334Изменено в версии 3.5.1.3536#### `AbstractEventLoop.run_until_complete(future)`3738Выполняется до завершения [`Future`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Future).3940Если аргумент является [объектом корутины](https://python-all.ru/3.6/library/asyncio-task.html#coroutine), он оборачивается с помощью [`ensure_future()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.ensure_future).4142Возвращает результат Future или возбуждает его исключение.4344#### `AbstractEventLoop.is_running()`4546Возвращает статус выполнения цикла событий.4748#### `AbstractEventLoop.stop()`4950Останавливает выполнение цикла событий.5152Это приводит к выходу из [`run_forever()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_forever) при следующей удобной возможности (см. там подробнее).5354Изменено в версии 3.5.1.5556#### `AbstractEventLoop.is_closed()`5758Возвращает `True`, если цикл событий был закрыт.5960Новое в версии 3.4.2.6162#### `AbstractEventLoop.close()`6364Закрывает цикл событий. Цикл не должен выполняться. Ожидающие колбэки будут потеряны.6566Это очищает очереди и завершает работу исполнителя, но не дожидается его полной остановки.6768Это идемпотентно и необратимо. После этого метода не следует вызывать никакие другие методы.6970#### `coroutine AbstractEventLoop.shutdown_asyncgens()`7172Планирует закрытие всех текущих открытых [асинхронных генераторов](https://python-all.ru/3.6/glossary.html#term-asynchronous-generator) с помощью вызова [`aclose()`](https://python-all.ru/3.6/reference/expressions.html#agen.aclose). После вызова этого метода цикл событий будет выдавать предупреждение при каждой итерации нового асинхронного генератора. Следует использовать для надёжного завершения всех запланированных асинхронных генераторов. Пример:7374```python75try:76 loop.run_forever()77finally:78 loop.run_until_complete(loop.shutdown_asyncgens())79 loop.close()80```8182Новое в версии 3.6.8384## 18.5.1.2. Вызовы8586Большинство функций [`asyncio`](https://python-all.ru/3.6/library/asyncio.html#module-asyncio) не принимают именованные аргументы. Если вы хотите передать именованные аргументы в свой колбэк, используйте [`functools.partial()`](https://python-all.ru/3.6/library/functools.html#functools.partial). Например, `loop.call_soon(functools.partial(print, "Hello", flush=True))` вызовет `print("Hello", flush=True)`.8788> **Примечание**89>90> [`functools.partial()`](https://python-all.ru/3.6/library/functools.html#functools.partial) лучше, чем функции `lambda`, потому что [`asyncio`](https://python-all.ru/3.6/library/asyncio.html#module-asyncio) может проверять объект [`functools.partial()`](https://python-all.ru/3.6/library/functools.html#functools.partial) для отображения параметров в режиме отладки, в то время как функции `lambda` имеют плохое представление.9192#### `AbstractEventLoop.call_soon(callback, *args)`9394Планирует вызов колбэка как можно скорее. Колбэк вызывается после возврата [`call_soon()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_soon), когда управление возвращается в цикл событий.9596Эта очередь работает по принципу FIFO; колбэки вызываются в порядке их регистрации. Каждый колбэк будет вызван ровно один раз.9798Любые позиционные аргументы, указанные после колбэка, будут переданы ему при вызове.99100Возвращается экземпляр [`asyncio.Handle`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Handle), который можно использовать для отмены колбэка.101102[Используйте functools.partial для передачи именованных аргументов колбэку](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).103104#### `AbstractEventLoop.call_soon_threadsafe(callback, *args)`105106Аналогично [`call_soon()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_soon), но потокобезопасно.107108См. раздел [concurrency and multithreading](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading) документации.109110## 18.5.1.3. Отложенные вызовы111112Цикл событий имеет собственные внутренние часы для вычисления тайм-аутов. Какие именно часы используются, зависит от реализации цикла событий (зависящей от платформы); в идеале это монотонные часы. Обычно это другие часы, нежели [`time.time()`](https://python-all.ru/3.6/library/time.html#time.time).113114> **Примечание**115>116> Тайм-ауты (относительная *задержка* или абсолютное *время*) не должны превышать одних суток.117118#### `AbstractEventLoop.call_later(delay, callback, *args)`119120Организует вызов *колбэка* через заданную *задержку* в секундах (целое число или float).121122Возвращается экземпляр [`asyncio.Handle`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Handle), который можно использовать для отмены колбэка.123124*Колбэк* будет вызван ровно один раз на каждый вызов [`call_later()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_later). Если два колбэка запланированы на одно и то же время, порядок их вызова не определён.125126Необязательные позиционные *args* будут переданы колбэку при его вызове. Если нужно передать колбэку именованные аргументы, используйте замыкание или [`functools.partial()`](https://python-all.ru/3.6/library/functools.html#functools.partial).127128[Используйте functools.partial для передачи именованных аргументов колбэку](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).129130#### `AbstractEventLoop.call_at(when, callback, *args)`131132Организует вызов *колбэка* в указанную абсолютную метку времени *when* (целое число или float), используя ту же систему отсчёта времени, что и [`AbstractEventLoop.time()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.time).133134Поведение этого метода аналогично [`call_later()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_later).135136Возвращается экземпляр [`asyncio.Handle`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Handle), который можно использовать для отмены колбэка.137138[Используйте functools.partial для передачи именованных аргументов колбэку](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).139140#### `AbstractEventLoop.time()`141142Возвращает текущее время в виде значения [`float`](https://python-all.ru/3.6/library/functions.html#float) в соответствии с внутренними часами цикла событий.143144> **См. также**145>146> Функция [`asyncio.sleep()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.sleep).147148## 18.5.1.4. Future149150#### `AbstractEventLoop.create_future()`151152Создаёт объект [`asyncio.Future`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Future), привязанный к циклу событий.153154Это предпочтительный способ создания Future-объектов в asyncio, поскольку реализации цикла событий могут предоставлять альтернативные реализации класса Future (с улучшенной производительностью или инструментарием).155156Новое в версии 3.5.2.157158## 18.5.1.5. Задачи159160#### `AbstractEventLoop.create_task(coro)`161162Планирует выполнение [объекта корутины](https://python-all.ru/3.6/library/asyncio-task.html#coroutine): оборачивает его в future. Возвращает объект [`Task`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Task).163164Сторонние циклы событий могут использовать собственный подкласс [`Task`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Task) для взаимодействия. В этом случае тип результата – подкласс [`Task`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Task).165166Этот метод был добавлен в Python 3.4.2. Используйте функцию [`async()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.async) для поддержки более старых версий Python.167168Новое в версии 3.4.2.169170#### `AbstractEventLoop.set_task_factory(factory)`171172Устанавливает фабрику задач, которая будет использоваться [`AbstractEventLoop.create_task()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_task).173174Если *factory* равно `None`, будет установлена фабрика задач по умолчанию.175176Если *factory* является *вызываемым объектом*, его сигнатура должна соответствовать `(loop, coro)`, где *loop* – ссылка на активный цикл событий, *coro* – объект корутины. Вызываемый объект должен возвращать объект, совместимый с [`asyncio.Future`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Future).177178Новое в версии 3.4.4.179180#### `AbstractEventLoop.get_task_factory()`181182Возвращает фабрику задач или `None`, если используется стандартная.183184Новое в версии 3.4.4.185186## 18.5.1.6. Создание соединений187188#### `coroutine AbstractEventLoop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None)`189190Создаёт потоковое транспортное соединение с указанными интернет-хостом *host* и портом *port*: семейство сокетов [`AF_INET`](https://python-all.ru/3.6/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.6/library/socket.html#socket.AF_INET6) в зависимости от *host* (или *family*, если указано), тип сокета [`SOCK_STREAM`](https://python-all.ru/3.6/library/socket.html#socket.SOCK_STREAM). *protocol\_factory* должен быть вызываемым объектом, возвращающим экземпляр [протокола](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-protocol).191192Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine), которая пытается установить соединение в фоновом режиме. В случае успеха корутина возвращает пару `(transport, protocol)`.193194Хронологическая последовательность выполняемой операции следующая:1951961. Соединение установлено, и создаётся [транспорт](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-transport), представляющий его.1972. *protocol\_factory* вызывается без аргументов и должен возвращать экземпляр [протокола](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-protocol).1983. Экземпляр протокола привязывается к транспорту, и вызывается его метод `connection_made()`.1994. Корутина успешно возвращает пару `(transport, protocol)`.200201Созданный транспорт является двунаправленным потоком, зависящим от реализации.202203> **Примечание**204>205> *protocol\_factory* может быть любым вызываемым объектом, не обязательно классом. Например, если нужно использовать уже созданный экземпляр протокола, можно передать `lambda: my_protocol`.206207Параметры, изменяющие способ создания соединения:208209- *ssl*: если указан и не равен false, создаётся SSL/TLS транспорт (по умолчанию создаётся обычный TCP транспорт). Если *ssl* является объектом [`ssl.SSLContext`](https://python-all.ru/3.6/library/ssl.html#ssl.SSLContext), этот контекст используется для создания транспорта; если *ssl* равен [`True`](https://python-all.ru/3.6/library/constants.html#True), используется контекст с некоторыми неопределёнными настройками по умолчанию.210211 > **См. также**212 >213 > [Вопросы безопасности SSL/TLS](https://python-all.ru/3.6/library/ssl.html#ssl-security)214- *server\_hostname* используется только вместе с *ssl* и задаёт или переопределяет имя хоста, с которым будет сравниваться сертификат целевого сервера. По умолчанию используется значение аргумента *host*. Если *host* пуст, значение по умолчанию отсутствует, и необходимо передать значение для *server\_hostname*. Если *server\_hostname* является пустой строкой, проверка имени хоста отключается (что представляет серьёзную угрозу безопасности, допуская атаки man-in-the-middle).215- *family*, *proto*, *flags* – необязательные семейство адресов, протокол и флаги, которые передаются в getaddrinfo() для разрешения *host*. Если заданы, все они должны быть целыми числами из соответствующих констант модуля [`socket`](https://python-all.ru/3.6/library/socket.html#module-socket).216- Если задан *sock*, он должен быть существующим, уже подключённым объектом [`socket.socket`](https://python-all.ru/3.6/library/socket.html#socket.socket), который будет использоваться транспортом. Если *sock* задан, ни один из параметров *host*, *port*, *family*, *proto*, *flags* и *local\_addr* не должен быть указан.217- *local\_addr*, если указан, представляет собой кортеж `(local_host, local_port)`, используемый для локальной привязки сокета. *local\_host* и *local\_port* ищутся с помощью getaddrinfo(), аналогично *host* и *port*.218219Изменено в версии 3.5: В Windows с [`ProactorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.ProactorEventLoop) теперь поддерживается SSL/TLS.220221> **См. также**222>223> Функция [`open_connection()`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.open_connection) может использоваться для получения пары ([`StreamReader`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.StreamReader), [`StreamWriter`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.StreamWriter)) вместо протокола.224225#### `coroutine AbstractEventLoop.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)`226227> **Примечание**228>229> Параметр *reuse\_address* больше не поддерживается, так как использование `SO_REUSEADDR` создаёт серьёзную угрозу безопасности для UDP. Явная передача `reuse_address=True` вызовет исключение.230>231> Когда несколько процессов с разными UID назначают сокеты одному и тому же адресу UDP-сокета с помощью `SO_REUSEADDR`, входящие пакеты могут случайным образом распределяться между сокетами.232>233> На поддерживаемых платформах *reuse\_port* можно использовать как замену аналогичной функциональности. С *reuse\_port* используется `SO_REUSEPORT`, что не позволяет процессам с разными UID назначать сокеты на один и тот же адрес сокета.234235Создать датаграммное соединение.236237Создание датаграммного соединения: семейство сокетов [`AF_INET`](https://python-all.ru/3.6/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.6/library/socket.html#socket.AF_INET6) в зависимости от *host* (или *family*, если указано), тип сокета [`SOCK_DGRAM`](https://python-all.ru/3.6/library/socket.html#socket.SOCK_DGRAM). *protocol\_factory* должен быть вызываемым объектом, возвращающим экземпляр [протокола](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-protocol).238239Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine), которая пытается установить соединение в фоновом режиме. В случае успеха корутина возвращает пару `(transport, protocol)`.240241Параметры, изменяющие способ создания соединения:242243- *local\_addr*, если задан, представляет собой кортеж `(local_host, local_port)`, используемый для привязки сокета локально. *local\_host* и *local\_port* разрешаются с помощью [`getaddrinfo()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.getaddrinfo).244- *remote\_addr*, если задан, представляет собой кортеж `(remote_host, remote_port)`, используемый для подключения сокета к удалённому адресу. *remote\_host* и *remote\_port* разрешаются с помощью [`getaddrinfo()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.getaddrinfo).245- *family*, *proto*, *flags* – необязательные семейство адресов, протокол и флаги, передаваемые в [`getaddrinfo()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.getaddrinfo) для разрешения *host*. Если заданы, все они должны быть целыми числами из соответствующих констант модуля [`socket`](https://python-all.ru/3.6/library/socket.html#module-socket).246- *reuse\_port* сообщает ядру, что данная конечная точка может быть привязана к тому же порту, что и другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Этот параметр не поддерживается в Windows и некоторых UNIX. Если константа `SO_REUSEPORT` не определена, эта возможность не поддерживается.247- *allow\_broadcast* указывает ядру разрешить этой конечной точке отправлять сообщения на широковещательный адрес.248- *sock* может быть указан необязательно, чтобы использовать уже существующий, подключённый объект [`socket.socket`](https://python-all.ru/3.6/library/socket.html#socket.socket) для транспорта. Если указан, *local\_addr* и *remote\_addr* должны быть опущены (должны быть [`None`](https://python-all.ru/3.6/library/constants.html#None)).249250В Windows с [`ProactorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.ProactorEventLoop) этот метод не поддерживается.251252См. примеры [протокол UDP-клиента эхо](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-udp-echo-client-protocol) и [протокол UDP-сервера эхо](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-udp-echo-server-protocol).253254Изменено в версии 3.4.4: Добавлены параметры *family*, *proto*, *flags*, *reuse\_address*, *reuse\_port, \*allow\_broadcast* и *sock*.255256Изменено в версии 3.6.10: Параметр *reuse\_address* больше не поддерживается по соображениям безопасности.257258#### `coroutine AbstractEventLoop.create_unix_connection(protocol_factory, path, *, ssl=None, sock=None, server_hostname=None)`259260Создание UNIX-соединения: семейство сокетов [`AF_UNIX`](https://python-all.ru/3.6/library/socket.html#socket.AF_UNIX), тип сокета [`SOCK_STREAM`](https://python-all.ru/3.6/library/socket.html#socket.SOCK_STREAM). Семейство сокетов [`AF_UNIX`](https://python-all.ru/3.6/library/socket.html#socket.AF_UNIX) используется для эффективного взаимодействия между процессами на одной машине.261262Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine), которая пытается установить соединение в фоновом режиме. В случае успеха корутина возвращает пару `(transport, protocol)`.263264*path* – это имя сокета домена UNIX и требуется, если не указан параметр *sock*. Поддерживаются абстрактные UNIX-сокеты, пути [`str`](https://python-all.ru/3.6/library/stdtypes.html#str) и [`bytes`](https://python-all.ru/3.6/library/stdtypes.html#bytes).265266О параметрах см. метод [`AbstractEventLoop.create_connection()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_connection).267268Доступность: UNIX.269270## 18.5.1.7. Создание слушающих соединений271272#### `coroutine AbstractEventLoop.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)`273274Создаёт TCP-сервер (тип сокета [`SOCK_STREAM`](https://python-all.ru/3.6/library/socket.html#socket.SOCK_STREAM)), привязанный к *host* и *port*.275276Возвращает объект [`Server`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Server), его атрибут [`sockets`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Server.sockets) содержит созданные сокеты. Используйте метод [`Server.close()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Server.close) для остановки сервера: закрыть слушающие сокеты.277278Параметры:279280- Параметр *host* может быть строкой; в этом случае TCP-сервер привязывается к *host* и *port*. Параметр *host* также может быть последовательностью строк, и тогда TCP-сервер привязывается ко всем хостам из этой последовательности. Если *host* – пустая строка или `None`, подразумеваются все интерфейсы, и будет возвращён список из нескольких сокетов (скорее всего, один для IPv4 и один для IPv6).281- *family* можно установить в [`socket.AF_INET`](https://python-all.ru/3.6/library/socket.html#socket.AF_INET) или [`AF_INET6`](https://python-all.ru/3.6/library/socket.html#socket.AF_INET6), чтобы заставить сокет использовать IPv4 или IPv6. Если не установлено, значение будет определено из host (по умолчанию `socket.AF_UNSPEC`).282- *flags* – битовая маска для [`getaddrinfo()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.getaddrinfo).283- *sock* можно указать, чтобы использовать уже существующий объект сокета. Если он указан, *host* и *port* следует опустить (они должны быть [`None`](https://python-all.ru/3.6/library/constants.html#None)).284- *backlog* – максимальное количество соединений в очереди, передаваемое в [`listen()`](https://python-all.ru/3.6/library/socket.html#socket.socket.listen) (по умолчанию 100).285- *ssl* можно установить в [`SSLContext`](https://python-all.ru/3.6/library/ssl.html#ssl.SSLContext), чтобы включить SSL для принятых соединений.286- *reuse\_address* указывает ядру повторно использовать локальный сокет в состоянии TIME\_WAIT, не дожидаясь истечения его естественного таймаута. Если не указано, автоматически устанавливается в `True` на UNIX.287- *reuse\_port* указывает ядру разрешить привязку этой конечной точки к тому же порту, к которому привязаны другие существующие конечные точки, при условии, что все они устанавливают этот флаг при создании. Эта опция не поддерживается в Windows.288289Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).290291Изменено в версии 3.5: На Windows с [`ProactorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.ProactorEventLoop) теперь поддерживается SSL/TLS.292293> **См. также**294>295> Функция [`start_server()`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.start_server) создаёт пару ([`StreamReader`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.StreamReader), [`StreamWriter`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.StreamWriter)) и вызывает колбэк с этой парой.296297Изменено в версии 3.5.1: Параметр *host* теперь может быть последовательностью строк.298299#### `coroutine AbstractEventLoop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None)`300301Аналогично [`AbstractEventLoop.create_server()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_server), но для семейства сокетов [`AF_UNIX`](https://python-all.ru/3.6/library/socket.html#socket.AF_UNIX).302303Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).304305Доступность: UNIX.306307#### `coroutine BaseEventLoop.connect_accepted_socket(protocol_factory, sock, *, ssl=None)`308309Обработать принятое соединение.310311Это используется серверами, которые принимают соединения вне asyncio, но используют asyncio для их обработки.312313Параметры:314315- *sock* – это уже существующий объект сокета, возвращённый вызовом `accept`.316- *ssl* можно установить в [`SSLContext`](https://python-all.ru/3.6/library/ssl.html#ssl.SSLContext), чтобы включить SSL для принятых соединений.317318Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine). После завершения корутина возвращает пару `(transport, protocol)`.319320Новое в версии 3.5.3.321322## 18.5.1.8. Наблюдение за файловыми дескрипторами323324На Windows с [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) поддерживаются только дескрипторы сокетов (например, файловые дескрипторы каналов не поддерживаются).325326На Windows с [`ProactorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.ProactorEventLoop) эти методы не поддерживаются.327328#### `AbstractEventLoop.add_reader(fd, callback, *args)`329330Начать наблюдение за файловым дескриптором на готовность к чтению и затем вызвать *колбэк* с указанными аргументами.331332[Используйте functools.partial, чтобы передать именованные аргументы в колбэк](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).333334#### `AbstractEventLoop.remove_reader(fd)`335336Прекратить наблюдение за файловым дескриптором на готовность к чтению.337338#### `AbstractEventLoop.add_writer(fd, callback, *args)`339340Начать наблюдение за файловым дескриптором на готовность к записи и затем вызвать *колбэк* с указанными аргументами.341342[Используйте functools.partial, чтобы передать именованные аргументы в колбэк](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).343344#### `AbstractEventLoop.remove_writer(fd)`345346Прекратить наблюдение за файловым дескриптором на готовность к записи.347348Пример [наблюдения за файловым дескриптором на события чтения](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-watch-read-event) использует низкоуровневый метод [`AbstractEventLoop.add_reader()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.add_reader) для регистрации файлового дескриптора сокета.349350## 18.5.1.9. Низкоуровневые операции с сокетами351352#### `coroutine AbstractEventLoop.sock_recv(sock, nbytes)`353354Получает данные из сокета. Аналогично блокирующему методу [`socket.socket.recv()`](https://python-all.ru/3.6/library/socket.html#socket.socket.recv).355356Возвращаемое значение – объект bytes, представляющий полученные данные. Максимальный объём данных, который можно получить за один раз, задаётся параметром *nbytes*.357358В [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) цикле событий сокет *sock* должен быть неблокирующим.359360Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).361362#### `coroutine AbstractEventLoop.sock_sendall(sock, data)`363364Отправляет данные в сокет. Аналогично блокирующему методу [`socket.socket.sendall()`](https://python-all.ru/3.6/library/socket.html#socket.socket.sendall).365366Сокет должен быть подключён к удалённому сокету. Этот метод продолжает отправлять данные из *data*, пока либо не будут отправлены все данные, либо не произойдёт ошибка. В случае успеха возвращается `None`. При ошибке возникает исключение, и невозможно определить, сколько данных (если вообще какие-то) было успешно обработано принимающей стороной соединения.367368В [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) цикле событий сокет *sock* должен быть неблокирующим.369370Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).371372#### `coroutine AbstractEventLoop.sock_connect(sock, address)`373374Подключается к удалённому сокету по адресу *address*. Аналогично блокирующему методу [`socket.socket.connect()`](https://python-all.ru/3.6/library/socket.html#socket.socket.connect).375376В [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) цикле событий сокет *sock* должен быть неблокирующим.377378Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).379380Изменено в версии 3.5.2: `address` больше не требует разрешения. `sock_connect` попытается проверить, разрешён ли уже *address*, вызвав [`socket.inet_pton()`](https://python-all.ru/3.6/library/socket.html#socket.inet_pton). Если нет, [`AbstractEventLoop.getaddrinfo()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.getaddrinfo) будет использован для разрешения *address*.381382> **См. также**383>384> [`AbstractEventLoop.create_connection()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_connection) и [`asyncio.open_connection()`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.open_connection).385386#### `coroutine AbstractEventLoop.sock_accept(sock)`387388Принимает соединение. Аналогично блокирующему [`socket.socket.accept()`](https://python-all.ru/3.6/library/socket.html#socket.socket.accept).389390Сокет должен быть привязан к адресу и ожидать подключения. Возвращаемое значение – пара `(conn, address)`, где *conn* – это *новый* объект сокета, пригодный для отправки и получения данных по соединению, а *address* – адрес, привязанный к сокету на другом конце соединения.391392Сокет *sock* должен быть неблокирующим.393394Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).395396> **См. также**397>398> [`AbstractEventLoop.create_server()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_server) и [`start_server()`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.start_server).399400## 18.5.1.10. Разрешение имени хоста401402#### `coroutine AbstractEventLoop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)`403404Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine), аналогичная функции [`socket.getaddrinfo()`](https://python-all.ru/3.6/library/socket.html#socket.getaddrinfo), но неблокирующая.405406#### `coroutine AbstractEventLoop.getnameinfo(sockaddr, flags=0)`407408Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine), аналогичная функции [`socket.getnameinfo()`](https://python-all.ru/3.6/library/socket.html#socket.getnameinfo), но неблокирующая.409410## 18.5.1.11. Подключение каналов411412В Windows с [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) эти методы не поддерживаются. Используйте [`ProactorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.ProactorEventLoop) для поддержки каналов в Windows.413414#### `coroutine AbstractEventLoop.connect_read_pipe(protocol_factory, pipe)`415416Регистрирует канал чтения в цикле событий.417418*protocol\_factory* должен создавать объект с интерфейсом [`Protocol`](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio.Protocol). *pipe* – это [объект, подобный файлу](https://python-all.ru/3.6/glossary.html#term-file-object). Возвращает пару `(transport, protocol)`, где *транспорт* поддерживает интерфейс [`ReadTransport`](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio.ReadTransport).419420При [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) цикле событий канал *pipe* переводится в неблокирующий режим.421422Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).423424#### `coroutine AbstractEventLoop.connect_write_pipe(protocol_factory, pipe)`425426Регистрирует канал записи в цикле событий.427428*protocol\_factory* должен создавать объект с интерфейсом `BaseProtocol`. *pipe* – это [объект, подобный файлу](https://python-all.ru/3.6/glossary.html#term-file-object). Возвращает пару `(transport, protocol)`, где *транспорт* поддерживает интерфейс [`WriteTransport`](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio.WriteTransport).429430При [`SelectorEventLoop`](https://python-all.ru/3.6/library/asyncio-eventloops.html#asyncio.SelectorEventLoop) цикле событий канал *pipe* переводится в неблокирующий режим.431432Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).433434> **См. также**435>436> Методы [`AbstractEventLoop.subprocess_exec()`](https://python-all.ru/3.6/library/asyncio-subprocess.html#asyncio.AbstractEventLoop.subprocess_exec) и [`AbstractEventLoop.subprocess_shell()`](https://python-all.ru/3.6/library/asyncio-subprocess.html#asyncio.AbstractEventLoop.subprocess_shell).437438## 18.5.1.12. Сигналы UNIX439440Доступно: только UNIX.441442#### `AbstractEventLoop.add_signal_handler(signum, callback, *args)`443444Добавляет обработчик сигнала.445446Вызывает [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError), если номер сигнала недопустим или его невозможно перехватить. Вызывает [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError), если возникла проблема при установке обработчика.447448[Используйте functools.partial для передачи именованных аргументов в колбэк](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).449450#### `AbstractEventLoop.remove_signal_handler(sig)`451452Удаляет обработчик сигнала.453454Возвращает `True`, если обработчик сигнала был удалён, и `False` в противном случае.455456> **См. также**457>458> Модуль [`signal`](https://python-all.ru/3.6/library/signal.html#module-signal).459460## 18.5.1.13. Исполнитель461462Вызывает функцию в [`Executor`](https://python-all.ru/3.6/library/concurrent.futures.html#concurrent.futures.Executor) (пуле потоков или пуле процессов). По умолчанию цикл событий использует исполнитель с пулом потоков ([`ThreadPoolExecutor`](https://python-all.ru/3.6/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor)).463464#### `coroutine AbstractEventLoop.run_in_executor(executor, func, *args)`465466Планирует вызов функции *func* в указанном исполнителе.467468Аргумент *исполнитель* должен быть экземпляром [`Executor`](https://python-all.ru/3.6/library/concurrent.futures.html#concurrent.futures.Executor) Исполнитель по умолчанию используется, если *исполнитель* равен `None`.469470[Используйте functools.partial для передачи именованных аргументов в \*func\*](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio-pass-keywords).471472Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).473474Изменено в версии 3.5.3: `BaseEventLoop.run_in_executor()` больше не настраивает `max_workers` создаваемого исполнителя пула потоков, оставляя настройку по умолчанию самому исполнителю пула потоков ([`ThreadPoolExecutor`](https://python-all.ru/3.6/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor)).475476#### `AbstractEventLoop.set_default_executor(executor)`477478Устанавливает исполнитель по умолчанию, используемый [`run_in_executor()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_in_executor).479480## 18.5.1.14. API обработки ошибок481482Позволяет настраивать обработку исключений в цикле событий.483484#### `AbstractEventLoop.set_exception_handler(handler)`485486Устанавливает *handler* в качестве нового обработчика исключений цикла событий.487488Если *handler* равен `None`, будет установлен обработчик исключений по умолчанию.489490Если *handler* – вызываемый объект, его сигнатура должна совпадать с `(loop, context)`, где `loop` будет ссылкой на активный цикл событий, `context` будет объектом `dict` (см. документацию [`call_exception_handler()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_exception_handler) для подробностей о контексте).491492#### `AbstractEventLoop.get_exception_handler()`493494Возвращает обработчик исключений или `None`, если используется стандартный.495496Новое в версии 3.5.2.497498#### `AbstractEventLoop.default_exception_handler(context)`499500Обработчик исключений по умолчанию.501502Вызывается при возникновении исключения, когда не установлен обработчик исключений, а также может вызываться пользовательским обработчиком исключений, который хочет передать управление стандартному поведению.503504Параметр *context* имеет то же значение, что и в [`call_exception_handler()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_exception_handler).505506#### `AbstractEventLoop.call_exception_handler(context)`507508Вызывает обработчик исключений текущего цикла событий.509510*context* – объект `dict`, содержащий следующие ключи (новые ключи могут быть добавлены позже):511512- ‘message’: сообщение об ошибке;513- 'исключение' (необязательно): объект исключения;514- ‘future’ (необязательно): экземпляр [`asyncio.Future`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.Future);515- ‘handle’ (необязательно): экземпляр [`asyncio.Handle`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Handle);516- 'протокол' (необязательно): экземпляр [Protocol](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-protocol);517- 'транспорт' (необязательно): экземпляр [Transport](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-transport);518- ‘socket’ (необязательно): экземпляр [`socket.socket`](https://python-all.ru/3.6/library/socket.html#socket.socket).519520> **Примечание**521>522> Примечание: этот метод не следует переопределять в подклассах циклов событий. Для любой пользовательской обработки исключений используйте метод [`set_exception_handler()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.set_exception_handler).523524## 18.5.1.15. Режим отладки525526#### `AbstractEventLoop.get_debug()`527528Возвращает режим отладки ([`bool`](https://python-all.ru/3.6/library/functions.html#bool)) цикла событий.529530Значение по умолчанию – `True`, если переменная окружения [`PYTHONASYNCIODEBUG`](https://python-all.ru/3.6/using/cmdline.html#envvar-PYTHONASYNCIODEBUG) имеет непустое строковое значение, и `False` в противном случае.531532Новое в версии 3.4.2.533534#### `AbstractEventLoop.set_debug(enabled: bool)`535536Устанавливает режим отладки цикла событий.537538Новое в версии 3.4.2.539540> **См. также**541>542> [Режим отладки asyncio](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-debug-mode).543544## 18.5.1.16. Сервер545546#### `class asyncio.Server`547548Сервер, прослушивающий сокеты.549550Объект, создаваемый методом [`AbstractEventLoop.create_server()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_server) и функцией [`start_server()`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.start_server). Не создавайте экземпляр класса напрямую.551552#### `close()`553554Прекращает обслуживание: закрывает слушающие сокеты и устанавливает атрибут [`sockets`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Server.sockets) в `None`.555556Сокеты существующих входящих подключений клиентов остаются открытыми.557558Сервер закрывается асинхронно, используйте [`wait_closed()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Server.wait_closed)\\nкорутину, чтобы дождаться закрытия сервера.559560#### `coroutine wait_closed()`561562Ожидайте завершения метода [`close()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.Server.close).563564Этот метод – [корутина](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).565566#### `sockets`567568Список объектов [`socket.socket`](https://python-all.ru/3.6/library/socket.html#socket.socket), которые прослушивает сервер, или `None`, если сервер закрыт.569570## 18.5.1.17. Обработчик571572#### `class asyncio.Handle`573574Объект-обёртка колбэка, возвращаемый функциями [`AbstractEventLoop.call_soon()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_soon), [`AbstractEventLoop.call_soon_threadsafe()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_soon_threadsafe), [`AbstractEventLoop.call_later()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_later) и [`AbstractEventLoop.call_at()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_at).575576#### `cancel()`577578Отменяет вызов. Если колбэк уже отменён или выполнен, этот метод ничего не делает.579580## 18.5.1.18. Примеры циклов событий581582### 18.5.1.18.1. Hello World с call\_soon()583584Пример использования метода [`AbstractEventLoop.call_soon()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_soon) для планирования колбэка. Колбэк выводит `"Hello World"` и затем останавливает цикл событий:585586```python587import asyncio588589def hello_world(loop):590 print('Hello World')591 loop.stop()592593loop = asyncio.get_event_loop()594595# Запланировать вызов hello_world()596loop.call_soon(hello_world, loop)597598# Блокирующий вызов прерван loop.stop()599loop.run_forever()600loop.close()601```602603> **См. также**604>605> Пример [корутины Hello World](https://python-all.ru/3.6/library/asyncio-task.html#asyncio-hello-world-coroutine) использует [корутину](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).606607### 18.5.1.18.2. Отображение текущей даты с помощью call\_later()608609Пример колбэка, который каждую секунду выводит текущую дату. Колбэк использует метод [`AbstractEventLoop.call_later()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_later), чтобы перепланировать себя на 5 секунд, а затем останавливает цикл событий:610611```python612import asyncio613import datetime614615def display_date(end_time, loop):616 print(datetime.datetime.now())617 if (loop.time() + 1.0) < end_time:618 loop.call_later(1, display_date, end_time, loop)619 else:620 loop.stop()621622loop = asyncio.get_event_loop()623624# Запланировать первый вызов display_date()625end_time = loop.time() + 5.0626loop.call_soon(display_date, end_time, loop)627628# Блокирующий вызов прерван loop.stop()629loop.run_forever()630loop.close()631```632633> **См. также**634>635> Пример [корутины, отображающей текущую дату](https://python-all.ru/3.6/library/asyncio-task.html#asyncio-date-coroutine) использует [корутину](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).636637### 18.5.1.18.3. Отслеживать файловый дескриптор на события чтения638639Ожидание, пока файловый дескриптор не получит некоторые данные, с помощью метода [`AbstractEventLoop.add_reader()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.add_reader), после чего цикл событий закрывается:640641```python642import asyncio643try:644 from socket import socketpair645except ImportError:646 from asyncio.windows_utils import socketpair647648# Создать пару связанных файловых дескрипторов649rsock, wsock = socketpair()650loop = asyncio.get_event_loop()651652def reader():653 data = rsock.recv(100)654 print("Received:", data.decode())655 # Готово: отменить регистрацию файлового дескриптора656 loop.remove_reader(rsock)657 # Остановить цикл событий658 loop.stop()659660# Зарегистрировать файловый дескриптор для события чтения661loop.add_reader(rsock, reader)662663# Симулировать приём данных из сети664loop.call_soon(wsock.send, 'abc'.encode())665666# Запустить цикл событий667loop.run_forever()668669# Мы закончили, закрываем сокеты и цикл событий670rsock.close()671wsock.close()672loop.close()673```674675> **См. также**676>677> Пример [регистрации открытого сокета для ожидания данных с помощью протокола](https://python-all.ru/3.6/library/asyncio-protocol.html#asyncio-register-socket) использует низкоуровневый протокол, созданный методом [`AbstractEventLoop.create_connection()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_connection).678>679> В примере [регистрации открытого сокета для ожидания данных с помощью потоков](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio-register-socket-streams) используются высокоуровневые потоки , созданные функцией [`open_connection()`](https://python-all.ru/3.6/library/asyncio-stream.html#asyncio.open_connection) в корутине.680681### 18.5.1.18.4. Установить обработчики сигналов для SIGINT и SIGTERM682683Зарегистрировать обработчики для сигналов `SIGINT` и `SIGTERM` с помощью метода [`AbstractEventLoop.add_signal_handler()`](https://python-all.ru/3.6/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.add_signal_handler):684685```python686import asyncio687import functools688import os689import signal690691def ask_exit(signame):692 print("got signal %s: exit" % signame)693 loop.stop()694695loop = asyncio.get_event_loop()696for signame in ('SIGINT', 'SIGTERM'):697 loop.add_signal_handler(getattr(signal, signame),698 functools.partial(ask_exit, signame))699700print("Event loop running forever, press Ctrl+C to interrupt.")701print("pid %s: send SIGINT or SIGTERM to exit." % os.getpid())702try:703 loop.run_forever()704finally:705 loop.close()706```707708Этот пример работает только на UNIX.709