8.13. ループ制御

ほとんどの asyncio スクリプトは、イベントループに直接触れることはありません。asyncio.run() で十分です。このページでは、そうでないケース(例外ハンドラのインストール、run とは異なるライフサイクルでのループの実行、計測のためにループオブジェクトを保持する場合)のための Loop のインターフェースを取り上げます。

8.13.1. ループの取得

  • asyncio.get_event_loop() -- Loop オブジェクトを返します。コルーチンの内側からでも外側からでも安全に呼び出せます。

  • asyncio.new_event_loop() -- MicroPython では、新しいループを作成するのではなく、既存のループの状態をリセット します。繰り返しておく価値のある注意点として、プログラムごとにイベントループはちょうど 1 つだけです。

Loop のメソッドと asyncio.run() 以外に、ループを 実行する ための API はありません。

8.13.2. ループを直接実行する

asyncio.run() は、ほぼすべてのアプリケーションにとって適切なエントリポイントです。そうでないケースのために、2 つの Loop メソッドが用意されています。

  • run_until_complete() -- awaitable を渡すと、その awaitable が完了するまでループを実行し、その結果を返します。1 回の asyncio.run() 呼び出しから、ループの後始末を省いたものに相当します。

  • run_forever() -- タスクの内側から stop() が呼び出されるまでループを実行します。トップレベルの awaitable はありません。アプリケーションは run_forever を呼び出す前に、必要なものを asyncio.create_task() でスケジュールしておくことが期待されます。

対になるメソッドは stop()(現在のタスクが完了した後にループを停止するよう要求する)と close()(ループのリソースを解放する)です。

8.13.3. ループ側でのタスク生成

  • create_task() -- asyncio.create_task() と同じ操作です。一般的なケースでアプリケーションコードがループの参照を必要としなくて済むように、独立した関数が存在します。一方、すでにループ参照を持っている計測のために、メソッドが存在します。

8.13.4. 例外ハンドラ

コルーチンの呼び出しチェーン内のどこでも捕捉されなかった例外をタスクが送出すると、ループはハンドラを呼び出します。典型的なケースは、アプリケーションが asyncio.create_task() で作成し、一度も await しなかったタスクです。既定のハンドラは sys.stderr 経由でトレースバックを表示します。例外 のページでは、それをカスタムなものに差し替える方法を示しました。

  • set_exception_handler() -- カスタムハンドラをインストールします。ハンドラは呼び出し可能な handler(loop, context) で、context は少なくとも 'message' を含み、通常は 'exception''future' も含む辞書です。

  • get_exception_handler() -- 現在インストールされているハンドラを返します。既定のものが使われている場合は None を返します。

  • default_exception_handler() -- 組み込みのハンドラです。既定の動作 実行したいカスタムハンドラの内部で役立ちます(たとえば、フラッシュにログを記録 しつつ トレースバックを表示する場合)。

  • call_exception_handler() -- 手動で構築したコンテキスト辞書を使って、現在インストールされているハンドラを実行します。主にループ自体が使うもので、アプリケーションが必要とすることはまれです。