【Python】イベントループでコルーチンを実行する:asyncio.run()

目次

概要

Pythonの非同期処理(asyncio)において、定義したコルーチン(async def)を実際に動作させるためのエントリーポイントとなる asyncio.run() 関数について解説します。

この関数は、イベントループの作成、コルーチンの実行、そして終了処理(ループのクローズ)までを一括で管理してくれる高レベルAPIです。

仕様(入出力)

  • 入力: 実行したいコルーチンオブジェクト(async def 関数の呼び出し結果)
  • 出力: コルーチンの戻り値(ある場合)
  • 機能:
    • 現在のスレッドで新しいイベントループを作成・設定する。
    • 指定されたコルーチンが完了するまで実行する。
    • 終了時にイベントループを閉じる。

構文と意味

構文引数例処理内容
asyncio.run(coro)main()新しいイベントループを開始し、コルーチン coro を実行して、完了後に結果を返します。Python 3.7以降の標準的な実行方法です。

基本の使い方

コルーチン関数を定義し、それを呼び出して生成されたコルーチンオブジェクトを asyncio.run() に渡します。

import asyncio

# 非同期関数の定義
async def main():
    print("main処理を実行中")
    return "result value"

if __name__ == "__main__":
    # 1. コルーチンオブジェクトの生成
    coroutine_obj = main()
    
    # 2. イベントループで実行
    result = asyncio.run(coroutine_obj)
    
    print(f"実行結果: {result}")

コード全文

イベントループがどのように処理を待機し、結果を返すかを確認するフローです。

import asyncio
import time

async def heavy_task():
    """時間がかかる処理をシミュレートするコルーチン"""
    print("[Task] 重い処理を開始します...")
    # 非同期に1秒待機(この間、イベントループは他の仕事があればそれをこなせます)
    await asyncio.sleep(1)
    print("[Task] 重い処理が完了しました")
    return "完了データ"

async def main():
    """メインのコルーチン"""
    print("[Main] イベントループが起動しました")
    
    # サブタスクの実行完了を待つ
    result = await heavy_task()
    
    print(f"[Main] タスクから結果を受け取りました: {result}")
    return "全工程終了"

if __name__ == "__main__":
    print("--- プログラム開始 ---")
    
    # ここでイベントループが作られ、main()が終わるまで動きます
    final_result = asyncio.run(main())
    
    print(f"--- プログラム終了 (戻り値: {final_result}) ---")

カスタムポイント

イベントループとは

非同期処理の心臓部です。「タスクの待ち行列(キュー)」を管理し、待機状態になったタスクがあれば別のタスクに切り替える、という処理を高速に繰り返す無限ループのようなものです。

asyncio.run() は、この複雑な仕組みのセットアップと後片付けを全自動で行ってくれます。

呼び出し方のバリエーション

通常は変数に入れずに、直接引数として渡す書き方が一般的です。

# 変数に入れる場合
obj = main()
asyncio.run(obj)

# 直接渡す場合(一般的)
asyncio.run(main())

注意点

  1. 二重起動の禁止
    • 既にイベントループが動いている場所(非同期関数の内部など)から、さらに asyncio.run() を呼ぶことはできません(RuntimeError になります)。
    • 非同期関数の中から別の非同期関数を呼びたい場合は、単に await 関数名() を使います。
  2. Jupyter Notebook / Google Colab
    • これらの環境では、既にバックグラウンドでイベントループが動いています。
    • そのため asyncio.run(main()) を実行すると「イベントループが既に実行中」というエラーになります。
    • Notebook上では、await main() と書くだけで実行できます。

まとめ

Python 3.7以降では、非同期処理の開始は asyncio.run(main()) が定石です。

「コルーチンは作って終わりではなく、イベントループに渡して初めて動く」という原則を理解しておきましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次