Runners¶
Source code: Lib/asyncio/runners.py
この節では、asyncio のコードを実行するための高レベルの asyncio のプリミティブの概略を解説します。
これらは イベントループ の上に構築されており、一般的な広く普及しているシナリオでの非同期コードの使用を簡素化することを目的としています。
非同期プログラムの実行¶
- asyncio.run(coro, *, debug=None)¶
coroutine coro を実行し、結果を返します。
This function runs the passed coroutine, taking care of managing the asyncio event loop, finalizing asynchronous generators, and closing the threadpool.
この関数は、同じスレッドで他の非同期イベントループが実行中のときは呼び出せません。
debug が
True
の場合、イベントループはデバッグモードで実行されます。False
は明示的にデバッグモードを無効化します。 グローバルな デバッグモード 設定を尊重するためにNone
が使用されます。This function always creates a new event loop and closes it at the end. It should be used as a main entry point for asyncio programs, and should ideally only be called once.
以下はプログラム例です:
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 context manager¶
- class asyncio.Runner(*, debug=None, loop_factory=None)¶
同じコンテキスト上での 複数 の非同期関数呼び出しをシンプルにするコンテキストマネージャ。
Sometimes several top-level async functions should be called in the same event loop and
contextvars.Context
.debug が
True
の場合、イベントループはデバッグモードで実行されます。False
は明示的にデバッグモードを無効化します。 グローバルな デバッグモード 設定を尊重するためにNone
が使用されます。loop_factory could be used for overriding the loop creation. It is the responsibility of the loop_factory to set the created loop as the current one. By default
asyncio.new_event_loop()
is used and set as current event loop withasyncio.set_event_loop()
if loop_factory isNone
.Basically,
asyncio.run()
example can be rewritten with the runner usage:async def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())
バージョン 3.11 で追加.
- run(coro, *, context=None)¶
Run a coroutine coro in the embedded loop.
Return the coroutine's result or raise its exception.
An optional keyword-only context argument allows specifying a custom
contextvars.Context
for the coro to run in. The runner's default context is used ifNone
.この関数は、同じスレッドで他の非同期イベントループが実行中のときは呼び出せません。
- close()¶
Close the runner.
Finalize asynchronous generators, shutdown default executor, close the event loop and release embedded
contextvars.Context
.
- get_loop()¶
Return the event loop associated with the runner instance.
注釈
Runner
uses the lazy initialization strategy, its constructor doesn't initialize underlying low-level structures.Embedded loop and context are created at the
with
body entering or the first call ofrun()
orget_loop()
.
Handling Keyboard Interruption¶
バージョン 3.11 で追加.
When signal.SIGINT
is raised by Ctrl-C, KeyboardInterrupt
exception is raised in the main thread by default. However this doesn't work with
asyncio
because it can interrupt asyncio internals and can hang the program from
exiting.
To mitigate this issue, asyncio
handles signal.SIGINT
as follows:
asyncio.Runner.run()
installs a customsignal.SIGINT
handler before any user code is executed and removes it when exiting from the function.The
Runner
creates the main task for the passed coroutine for its execution.When
signal.SIGINT
is raised by Ctrl-C, the custom signal handler cancels the main task by callingasyncio.Task.cancel()
which raisesasyncio.CancelledError
inside the main task. This causes the Python stack to unwind,try/except
andtry/finally
blocks can be used for resource cleanup. After the main task is cancelled,asyncio.Runner.run()
raisesKeyboardInterrupt
.A user could write a tight loop which cannot be interrupted by
asyncio.Task.cancel()
, in which case the second following Ctrl-C immediately raises theKeyboardInterrupt
without cancelling the main task.