asyncio-runner.md
1> **Источник:** https://python-all.ru/3.12/library/asyncio-runner.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Исполнители89**Исходный код:** [Lib/asyncio/runners.py](https://python-all.ru/src/3.12/Lib/asyncio/runners.py)1011В этом разделе описываются высокоуровневые примитивы asyncio для выполнения асинхронного кода.1213Они построены поверх [цикла событий](https://python-all.ru/3.12/library/asyncio-eventloop.html#asyncio-event-loop) с целью упростить использование асинхронного кода в распространённых сценариях.1415[Запуск asyncio-программы](https://python-all.ru/3.12/library/asyncio-runner.html#running-an-asyncio-program) [Контекстный менеджер Runner](https://python-all.ru/3.12/library/asyncio-runner.html#runner-context-manager) [Обработка прерывания с клавиатуры](https://python-all.ru/3.12/library/asyncio-runner.html#handling-keyboard-interruption)1617## [Запуск программы asyncio](https://python-all.ru/3.12/library/asyncio-runner.html#id1)1819#### `asyncio.run(coro, *, debug=None, loop_factory=None)`2021Выполняет [корутину](https://python-all.ru/3.12/glossary.html#term-coroutine) *coro* и возвращает результат.2223Эта функция запускает переданную корутину, заботясь об управлении циклом событий asyncio, *завершении асинхронных генераторов* и закрытии исполнителя.2425Эту функцию нельзя вызывать, когда в том же потоке выполняется другой цикл событий asyncio.2627Если *debug* равен `True`, цикл событий будет работать в режиме отладки. `False` явно отключает режим отладки. `None` используется для соблюдения глобальных настроек [режима отладки](https://python-all.ru/3.12/library/asyncio-dev.html#asyncio-debug-mode).2829Если *loop\_factory* не равен `None`, он используется для создания нового цикла событий; в противном случае используется [`asyncio.new_event_loop()`](https://python-all.ru/3.12/library/asyncio-eventloop.html#asyncio.new_event_loop). Цикл закрывается в конце. Эта функция должна использоваться как главная точка входа для программ asyncio и, в идеале, должна вызываться только один раз. Рекомендуется использовать *loop\_factory* для настройки цикла событий вместо политик.3031Исполнителю даётся тайм-аут в 5 минут для завершения. Если исполнитель не завершился за это время, выводится предупреждение и исполнитель закрывается.3233Пример:3435```python36async def main():37 await asyncio.sleep(1)38 print('hello')3940asyncio.run(main())41```4243Добавлено в версии 3.7.4445Изменено в версии 3.9: Обновлено для использования [`loop.shutdown_default_executor()`](https://python-all.ru/3.12/library/asyncio-eventloop.html#asyncio.loop.shutdown_default_executor).4647Изменено в версии 3.10: *debug* по умолчанию равен `None`, чтобы соблюдать глобальные настройки режима отладки.4849Изменено в версии 3.12: Добавлен параметр *loop\_factory*.5051## [Контекстный менеджер Runner](https://python-all.ru/3.12/library/asyncio-runner.html#id2)5253#### `class asyncio.Runner(*, debug=None, loop_factory=None)`5455Контекстный менеджер, упрощающий *множественные* вызовы асинхронных функций в одном контексте.5657Иногда несколько асинхронных функций верхнего уровня нужно вызывать в одном [цикле событий](https://python-all.ru/3.12/library/asyncio-eventloop.html#asyncio-event-loop) и [`contextvars.Context`](https://python-all.ru/3.12/library/contextvars.html#contextvars.Context).5859Если *debug* равен `True`, цикл событий будет работать в режиме отладки. `False` явно отключает режим отладки. `None` используется для соблюдения глобальных настроек [режима отладки](https://python-all.ru/3.12/library/asyncio-dev.html#asyncio-debug-mode).6061*loop\_factory* может использоваться для переопределения создания цикла. Ответственность *loop\_factory* – установить созданный цикл как текущий. По умолчанию используется [`asyncio.new_event_loop()`](https://python-all.ru/3.12/library/asyncio-eventloop.html#asyncio.new_event_loop) и устанавливается как текущий цикл событий с помощью [`asyncio.set_event_loop()`](https://python-all.ru/3.12/library/asyncio-eventloop.html#asyncio.set_event_loop), если *loop\_factory* равен `None`.6263В принципе, пример [`asyncio.run()`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.run) можно переписать с использованием runner:6465```python66async def main():67 await asyncio.sleep(1)68 print('hello')6970with asyncio.Runner() as runner:71 runner.run(main())72```7374Добавлено в версии 3.12.7576#### `run(coro, *, context=None)`7778Запускает [корутину](https://python-all.ru/3.12/glossary.html#term-coroutine) *coro* во встроенном цикле событий.7980Возвращает результат корутины или возбуждает её исключение.8182Необязательный аргумент *context* (только по ключу) позволяет указать пользовательский [`contextvars.Context`](https://python-all.ru/3.12/library/contextvars.html#contextvars.Context) для выполнения *coro*. Если `None`, используется контекст запускатора по умолчанию.8384Эту функцию нельзя вызывать, когда в том же потоке выполняется другой цикл событий asyncio.8586#### `close()`8788Закрывает runner.8990Завершает асинхронные генераторы, останавливает исполнитель по умолчанию, закрывает цикл событий и освобождает встроенный [`contextvars.Context`](https://python-all.ru/3.12/library/contextvars.html#contextvars.Context).9192#### `get_loop()`9394Возвращает цикл событий, связанный с экземпляром runner.9596> **Примечание**97>98> [`Runner`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.Runner) использует стратегию ленивой инициализации: его конструктор не инициализирует нижележащие низкоуровневые структуры.99>100> Встроенные *цикл событий* и *контекст* создаются при входе в тело [`with`](https://python-all.ru/3.12/reference/compound_stmts.html#with) или при первом вызове [`run()`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.run) или [`get_loop()`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.Runner.get_loop).101102## [Обработка прерывания с клавиатуры](https://python-all.ru/3.12/library/asyncio-runner.html#id3)103104Добавлено в версии 3.12.105106Когда [`signal.SIGINT`](https://python-all.ru/3.12/library/signal.html#signal.SIGINT) возбуждается `Ctrl`-`C`, по умолчанию в главном потоке возбуждается исключение [`KeyboardInterrupt`](https://python-all.ru/3.12/library/exceptions.html#KeyboardInterrupt). Однако это не работает с [`asyncio`](https://python-all.ru/3.12/library/asyncio.html#module-asyncio), поскольку оно может прервать внутренние механизмы asyncio и привести к зависанию программы при завершении.107108Чтобы смягчить эту проблему, [`asyncio`](https://python-all.ru/3.12/library/asyncio.html#module-asyncio) обрабатывает [`signal.SIGINT`](https://python-all.ru/3.12/library/signal.html#signal.SIGINT) следующим образом:1091101. [`asyncio.Runner.run()`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.Runner.run) устанавливает собственный обработчик [`signal.SIGINT`](https://python-all.ru/3.12/library/signal.html#signal.SIGINT) до выполнения любого пользовательского кода и удаляет его при выходе из функции.1112. [`Runner`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.Runner) создаёт главную задачу для переданной корутины для её выполнения.1123. Когда [`signal.SIGINT`](https://python-all.ru/3.12/library/signal.html#signal.SIGINT) возбуждается `Ctrl`-`C`, пользовательский обработчик сигнала отменяет главную задачу вызовом [`asyncio.Task.cancel()`](https://python-all.ru/3.12/library/asyncio-task.html#asyncio.Task.cancel), что возбуждает [`asyncio.CancelledError`](https://python-all.ru/3.12/library/asyncio-exceptions.html#asyncio.CancelledError) внутри главной задачи. Это приводит к разворачиванию стека Python, блоки `try/except` и `try/finally` можно использовать для очистки ресурсов. После отмены главной задачи [`asyncio.Runner.run()`](https://python-all.ru/3.12/library/asyncio-runner.html#asyncio.Runner.run) возбуждает [`KeyboardInterrupt`](https://python-all.ru/3.12/library/exceptions.html#KeyboardInterrupt).1134. Пользователь может написать плотный цикл, который не может быть прерван с помощью [`asyncio.Task.cancel()`](https://python-all.ru/3.12/library/asyncio-task.html#asyncio.Task.cancel); в этом случае второе нажатие `Ctrl`-`C` немедленно возбуждает [`KeyboardInterrupt`](https://python-all.ru/3.12/library/exceptions.html#KeyboardInterrupt) без отмены главной задачи.114