Документация Python неофициальный перевод

asyncio-runner.md

110 строк · 10.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.11/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.11/Lib/asyncio/runners.py)1011В этом разделе описываются высокоуровневые примитивы asyncio для выполнения асинхронного кода.1213Они построены поверх [цикла событий](https://python-all.ru/3.11/library/asyncio-eventloop.html#asyncio-event-loop) с целью упростить использование асинхронного кода в распространённых сценариях.1415[Запуск asyncio-программы](https://python-all.ru/3.11/library/asyncio-runner.html#running-an-asyncio-program) [Контекстный менеджер Runner](https://python-all.ru/3.11/library/asyncio-runner.html#runner-context-manager) [Обработка прерывания с клавиатуры](https://python-all.ru/3.11/library/asyncio-runner.html#handling-keyboard-interruption)1617## [Запуск программы asyncio](https://python-all.ru/3.11/library/asyncio-runner.html#id1)1819#### `asyncio.run(coro, *, debug=None)`2021Выполняет [корутину](https://python-all.ru/3.11/glossary.html#term-coroutine) *coro* и возвращает результат.2223Эта функция выполняет переданную корутину, беря на себя управление циклом событий asyncio, *завершение асинхронных генераторов* и закрытие пула потоков.2425Эту функцию нельзя вызывать, когда в том же потоке выполняется другой цикл событий asyncio.2627Если *debug* равен `True`, цикл событий будет работать в режиме отладки. `False` явно отключает режим отладки. `None` используется для соблюдения глобальных настроек [режима отладки](https://python-all.ru/3.11/library/asyncio-dev.html#asyncio-debug-mode).2829Эта функция всегда создаёт новый цикл событий и закрывает его в конце. Её следует использовать в качестве главной точки входа для программ asyncio, и в идеале она должна вызываться только один раз.3031Пример:3233```python34async def main():35    await asyncio.sleep(1)36    print('hello')3738asyncio.run(main())39```4041Добавлено в версии 3.7.4243Изменено в версии 3.9: Обновлено для использования [`loop.shutdown_default_executor()`](https://python-all.ru/3.11/library/asyncio-eventloop.html#asyncio.loop.shutdown_default_executor).4445Изменено в версии 3.10: *debug* по умолчанию равен `None`, чтобы соблюдать глобальные настройки режима отладки.4647## [Контекстный менеджер Runner](https://python-all.ru/3.11/library/asyncio-runner.html#id2)4849#### `class asyncio.Runner(*, debug=None, loop_factory=None)`5051Контекстный менеджер, упрощающий *множественные* вызовы асинхронных функций в одном контексте.5253Иногда несколько асинхронных функций верхнего уровня нужно вызывать в одном [цикле событий](https://python-all.ru/3.11/library/asyncio-eventloop.html#asyncio-event-loop) и [`contextvars.Context`](https://python-all.ru/3.11/library/contextvars.html#contextvars.Context).5455Если *debug* равен `True`, цикл событий будет работать в режиме отладки. `False` явно отключает режим отладки. `None` используется для соблюдения глобальных настроек [режима отладки](https://python-all.ru/3.11/library/asyncio-dev.html#asyncio-debug-mode).5657*loop\_factory* может использоваться для переопределения создания цикла. Ответственность *loop\_factory* – установить созданный цикл как текущий. По умолчанию используется [`asyncio.new_event_loop()`](https://python-all.ru/3.11/library/asyncio-eventloop.html#asyncio.new_event_loop) и устанавливается как текущий цикл событий с помощью [`asyncio.set_event_loop()`](https://python-all.ru/3.11/library/asyncio-eventloop.html#asyncio.set_event_loop), если *loop\_factory* равен `None`.5859В принципе, пример [`asyncio.run()`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.run) можно переписать с использованием runner:6061```python62async def main():63    await asyncio.sleep(1)64    print('hello')6566with asyncio.Runner() as runner:67    runner.run(main())68```6970Новое в версии 3.11.7172#### `run(coro, *, context=None)`7374Запускает [корутину](https://python-all.ru/3.11/glossary.html#term-coroutine) *coro* во встроенном цикле событий.7576Возвращает результат корутины или возбуждает её исключение.7778Необязательный аргумент *context* (только по ключу) позволяет указать пользовательский [`contextvars.Context`](https://python-all.ru/3.11/library/contextvars.html#contextvars.Context) для выполнения *coro*. Если `None`, используется контекст запускатора по умолчанию.7980Эту функцию нельзя вызывать, когда в том же потоке выполняется другой цикл событий asyncio.8182#### `close()`8384Закрывает runner.8586Завершает асинхронные генераторы, останавливает исполнитель по умолчанию, закрывает цикл событий и освобождает встроенный [`contextvars.Context`](https://python-all.ru/3.11/library/contextvars.html#contextvars.Context).8788#### `get_loop()`8990Возвращает цикл событий, связанный с экземпляром runner.9192> **Примечание**93>94> [`Runner`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.Runner) использует стратегию ленивой инициализации: его конструктор не инициализирует нижележащие низкоуровневые структуры.95>96> Встроенные *цикл событий* и *контекст* создаются при входе в тело [`with`](https://python-all.ru/3.11/reference/compound_stmts.html#with) или при первом вызове [`run()`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.run) или [`get_loop()`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.Runner.get_loop).9798## [Обработка прерывания с клавиатуры](https://python-all.ru/3.11/library/asyncio-runner.html#id3)99100Новое в версии 3.11.101102Когда [`signal.SIGINT`](https://python-all.ru/3.11/library/signal.html#signal.SIGINT) возбуждается `Ctrl-C`, в главном потоке по умолчанию возбуждается [`KeyboardInterrupt`](https://python-all.ru/3.11/library/exceptions.html#KeyboardInterrupt) исключение. Однако это не работает с [`asyncio`](https://python-all.ru/3.11/library/asyncio.html#module-asyncio), поскольку он может прервать внутренние механизмы asyncio и привести к зависанию программы при выходе.103104Чтобы смягчить эту проблему, [`asyncio`](https://python-all.ru/3.11/library/asyncio.html#module-asyncio) обрабатывает [`signal.SIGINT`](https://python-all.ru/3.11/library/signal.html#signal.SIGINT) следующим образом:1051061. [`asyncio.Runner.run()`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.Runner.run) устанавливает собственный обработчик [`signal.SIGINT`](https://python-all.ru/3.11/library/signal.html#signal.SIGINT) до выполнения любого пользовательского кода и удаляет его при выходе из функции.1072. [`Runner`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.Runner) создаёт главную задачу для переданной корутины для её выполнения.1083. Когда [`signal.SIGINT`](https://python-all.ru/3.11/library/signal.html#signal.SIGINT) возбуждается `Ctrl-C`, пользовательский обработчик сигнала отменяет главную задачу вызовом [`asyncio.Task.cancel()`](https://python-all.ru/3.11/library/asyncio-task.html#asyncio.Task.cancel), который возбуждает [`asyncio.CancelledError`](https://python-all.ru/3.11/library/asyncio-exceptions.html#asyncio.CancelledError) внутри главной задачи. Это приводит к развёртыванию стека Python; блоки `try/except` и `try/finally` могут использоваться для очистки ресурсов. После отмены главной задачи [`asyncio.Runner.run()`](https://python-all.ru/3.11/library/asyncio-runner.html#asyncio.Runner.run) возбуждает [`KeyboardInterrupt`](https://python-all.ru/3.11/library/exceptions.html#KeyboardInterrupt).1094. Пользователь может написать цикл с интенсивной работой, который не может быть прерван с помощью [`asyncio.Task.cancel()`](https://python-all.ru/3.11/library/asyncio-task.html#asyncio.Task.cancel); в этом случае второй вызов `Ctrl-C` немедленно возбуждает [`KeyboardInterrupt`](https://python-all.ru/3.11/library/exceptions.html#KeyboardInterrupt) без отмены главной задачи.110