Запускатели
Исходный код: Lib/asyncio/runners.py
В этом разделе описаны высокоуровневые примитивы asyncio для запуска кода asyncio.
Они построены на основе цикла событий и предназначены для упрощения использования асинхронного кода в распространённых сценариях.
Запуск программы asyncio
-
asyncio.run(coro, *, debug=None, loop_factory=None) -
Выполняет coro в цикле событий asyncio и возвращает результат.
Аргументом может быть любой объект, поддерживающий ожидание.
Эта функция запускает объект, поддерживающий ожидание, управляет циклом событий asyncio, завершает асинхронные генераторы и закрывает исполнитель.
Эту функцию нельзя вызывать, если в том же потоке уже работает другой цикл событий asyncio.
Если debug имеет значение
True, цикл событий будет запущен в режиме отладки.Falseявно отключает режим отладки.Noneиспользуется, чтобы учитывать глобальные настройки режима отладки.Если loop_factory не равен
None, он используется для создания нового цикла событий; в противном случае используетсяasyncio.new_event_loop(). Цикл закрывается по завершении. Эту функцию следует использовать в качестве основной точки входа в программы asyncio и в идеале вызывать только один раз. Для настройки цикла событий рекомендуется использовать loop_factory, а не политики. Передачаasyncio.EventLoopпозволяет запускать asyncio без системы политик.Исполнителю даётся 5 минут на завершение работы. Если за это время он не завершит работу, будет выдано предупреждение, и исполнитель будет закрыт.
Пример:
async def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())Добавлено в версии 3.7.
Изменено в версии 3.9: Обновлено для использования
loop.shutdown_default_executor().Изменено в версии 3.10: По умолчанию debug имеет значение
None, чтобы учитывать глобальные настройки режима отладки.Изменено в версии 3.12: Добавлен параметр loop_factory.
Изменено в версии 3.14: coro может быть любым объектом, поддерживающим ожидание.
Примечание
Система политик
asyncioобъявлена устаревшей и будет удалена в Python 3.16; после этого для настройки цикла событий потребуется явно указать loop_factory.
Менеджер контекста Runner
-
class asyncio.Runner(*, debug=None, loop_factory=None) -
Менеджер контекста, упрощающий выполнение нескольких асинхронных вызовов функций в одном контексте.
Иногда несколько асинхронных функций верхнего уровня нужно вызвать в одном и том же цикле событий и
contextvars.Context.Если debug имеет значение
True, цикл событий будет запущен в режиме отладки.Falseявно отключает режим отладки.Noneиспользуется, чтобы учитывать глобальные настройки режима отладки.Параметр loop_factory можно использовать для переопределения создания цикла. Обязанность установить созданный цикл в качестве текущего лежит на loop_factory. По умолчанию используется
asyncio.new_event_loop(), а если loop_factory имеет значениеNone, он устанавливается в качестве текущего цикла событий с помощьюasyncio.set_event_loop().Пример с
asyncio.run()можно переписать, используя runner:async def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())Добавлено в версии 3.11.
-
run(coro, *, context=None) -
Выполняет coro во встроенном цикле событий.
Аргументом может быть любой объект, поддерживающий ожидание.
Если аргумент является сопрограммой, она оборачивается в Task.
Необязательный именованный аргумент context позволяет указать пользовательский
contextvars.Context, в котором будет выполняться код. Если значение context равноNone, используется контекст runner по умолчанию.Возвращает результат объекта, поддерживающего ожидание, или вызывает исключение.
Эту функцию нельзя вызывать, если в том же потоке уже работает другой цикл событий asyncio.
Изменено в версии 3.14: coro может быть любым объектом, поддерживающим ожидание.
-
close() -
Закрывает runner.
Завершает асинхронные генераторы, останавливает исполнитель по умолчанию, закрывает цикл событий и освобождает встроенный
contextvars.Context.
-
get_loop() -
Возвращает цикл событий, связанный с экземпляром runner.
Примечание
Runnerиспользует стратегию отложенной инициализации: его конструктор не инициализирует нижележащие низкоуровневые структуры.Встроенные loop и context создаются при входе в тело
withили при первом вызовеrun()илиget_loop(). -
Обработка прерывания с клавиатуры
Добавлено в версии 3.11.
Когда при нажатии Ctrl-C возникает signal.SIGINT, в главном потоке по умолчанию вызывается исключение KeyboardInterrupt. Однако с asyncio это не работает, поскольку может прервать внутренние механизмы asyncio и помешать завершению программы.
Чтобы смягчить эту проблему, asyncio обрабатывает signal.SIGINT следующим образом:
-
asyncio.Runner.run()устанавливает пользовательский обработчикsignal.SIGINTдо выполнения любого пользовательского кода и удаляет его при выходе из функции. Runnerсоздаёт для выполнения корутины главный Task.- Когда при нажатии Ctrl-C возникает
signal.SIGINT, пользовательский обработчик сигнала отменяет главный Task, вызываяasyncio.Task.cancel(), что вызываетasyncio.CancelledErrorвнутри главного Task. В результате стек Python раскручивается; для очистки ресурсов можно использовать блокиtry/exceptиtry/finally. После отмены главного Taskasyncio.Runner.run()вызываетKeyboardInterrupt. - Пользователь может написать бесконечный цикл, который нельзя прервать с помощью
asyncio.Task.cancel(); в таком случае повторное нажатие Ctrl-C немедленно вызываетKeyboardInterrupt, не отменяя главный Task.
© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/library/asyncio-runner.html