Spec-Zone.ru › Python 3.13

Потоковые обработчики

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

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

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

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

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

asyncio.run(coro, *, debug=None, loop_factory=None)

Выполните корутину coro и верните результат.

Эта функция запускает переданную корутину, заботясь о управлении циклом событий 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.

Менеджер контекста потокового обработчика

class asyncio.Runner(*, debug=None, loop_factory=None)

Менеджер контекста, который упрощает многократные вызовы асинхронных функций в одном контексте.

Иногда несколько функций высшего уровня async должны вызываться в одном цикле событий и contextvars.Context.

Если debug равно True, цикл событий будет запущен в отладочном режиме. False явным образом отключает отладочный режим. None используется для соблюдения глобальных настроек Отладочного режима.

loop_factory можно использовать для переопределения создания цикла. Ответственность loop_factory состоит в том, чтобы установить созданный цикл в качестве текущего. По умолчанию используется asyncio.new_event_loop() и устанавливается в качестве текущего цикла событий с помощью asyncio.set_event_loop(), если loop_factory равен None.

В принципе, пример asyncio.run() можно переписать с использованием обработчика:

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.

Эта функция не может быть вызвана, когда другой цикл событий asyncio работает в том же потоке.

close()

Закрыть обработчик.

Завершить асинхронные генераторы, остановить исполнитель по умолчанию, закрыть цикл событий и освободить встроенный contextvars.Context.

get_loop()

Вернуть цикл событий, связанный с экземпляром обработчика.

Примечание

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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/asyncio-runner.html

Spec-Zone.ru

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