目次
概要
Pythonで非同期処理を行うための関数定義 async def と、その関数を呼び出した際に生成される特殊な戻り値「コルーチンオブジェクト」について解説します。
通常の関数(同期関数)とは異なり、async def で定義された関数は、呼び出しただけでは中の処理が実行されないという重要な特徴があります。
仕様(入出力)
- 入力:
async defで定義された関数の呼び出し - 出力:
coroutine型のオブジェクト(処理結果ではない) - 構文:
async def 関数名(引数):
基本の使い方
関数定義の先頭に async キーワードを付けます。
この関数を呼び出すと、関数の戻り値として即座に「コルーチンオブジェクト」が返されます。
import asyncio
# 非同期関数の定義
async def my_coroutine():
print("このメッセージは、ただ呼び出しただけでは表示されません")
return "完了"
# 関数の呼び出し
# ここではまだ関数の中身は実行されません!
obj = my_coroutine()
# 型の確認
print(type(obj)) # <class 'coroutine'>
コード全文
コルーチンオブジェクトが生成される様子と、実際にそれを実行して結果を取り出す(asyncio.run)までの流れを確認するコードです。
import asyncio
# 1. 非同期関数の定義 (async def)
async def main_task(name):
print(f"[{name}] 非同期関数が開始されました")
# 非同期処理のシミュレーション
await asyncio.sleep(1)
print(f"[{name}] 終了")
return f"{name}の結果"
# --- 実行確認 ---
if __name__ == "__main__":
print("--- 1. 関数を呼び出すだけの場合 ---")
# 通常の関数のように呼び出す
coro = main_task("Test1")
# 戻り値は結果ではなく「コルーチンオブジェクト」
print(f"戻り値の型: {type(coro)}")
print(f"オブジェクトの中身: {coro}")
# 注意: この時点では "非同期関数が開始されました" は表示されていません
# 未実行のコルーチンを放置すると RuntimeWarning が出ることがあります
coro.close() # 実行せずに閉じる
print("\n--- 2. イベントループで実行する場合 ---")
# asyncio.run() にコルーチンオブジェクトを渡すことで初めて実行される
result = asyncio.run(main_task("Test2"))
print(f"実行結果: {result}")
カスタムポイント
コルーチンの性質
| 項目 | 通常の関数 (def) | 非同期関数 (async def) |
| キーワード | def func(): | async def func(): |
| 呼び出し時 | 中身が即座に実行される | 実行されず、コルーチンオブジェクトを返す |
| 実行方法 | func() | await func() または asyncio.run(func()) |
| return値 | 計算結果 | 計算結果(awaitした後に受け取れる) |
注意点
- RuntimeWarning
obj = main()のようにコルーチンオブジェクトを作ったにもかかわらず、awaitもasyncio.run()もせずにプログラムを終了させると、Pythonは「コルーチンが実行されずに破棄されました」という警告(RuntimeWarning)を出します。
awaitの制限- 非同期関数の実行結果を待つための
awaitキーワードは、async defで定義された関数の中でしか使用できません。通常の関数内でawaitを書くと構文エラーになります。
- 非同期関数の実行結果を待つための
まとめ
async defは「コルーチンの設計図」を作ります。関数呼び出し()は「実行待ちのタスク(コルーチンオブジェクト)」を作ります。asyncio.run()またはawaitで初めて「実行」されます。
この「呼び出し」と「実行」が分離している点が、非同期処理の最大の特徴です。
