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