Spec-Zone.ru › Python 3.11

Запуск asyncio программ

Исходный код: Lib/asyncio/runners.py

В этом разделе описаны высокоуровневые asyncio-примитивы для запуска asyncio-кода.

Они основаны на цикле событий с целью упрощения использования асинхронного кода в распространённых сценариях.

  • Запуск asyncio программы
  • Менеджер контекста Runner
  • Обработка прерывания по нажатию клавиши

Запуск 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 следующим образом:

  1. asyncio.Runner.run() устанавливает пользовательскую обработку signal.SIGINT перед выполнением любого пользовательского кода и удаляет её при выходе из функции.
  2. Менеджер контекста Runner создаёт главную задачу для переданной корутины для её выполнения.
  3. При поднятии signal.SIGINT нажатием Ctrl-C, пользовательская обработчик сигнала отменяет главную задачу, вызывая asyncio.Task.cancel(), которая поднимает asyncio.CancelledError внутри главной задачи. Это заставляет стек Python развернуться, try/except и try/finally блоки могут использоваться для очистки ресурсов. После отмены главной задачи, asyncio.Runner.run() поднимает KeyboardInterrupt.
  4. Пользователь может написать плотный цикл, который не может быть прерван 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API