できない.dev

Python で「coroutine was never awaited」の警告が出て非同期処理が実行されない

async 関数は呼び出しただけでは実行されず、コルーチンオブジェクトを返すだけである。
await するか asyncio でスケジュールすると解決する。

公開:

要約

RuntimeWarning: coroutine '...' was never awaited は、async 関数を呼び出したのに await もスケジュールもしていないときに出る。
async 関数は呼んだだけでは実行されず、コルーチンオブジェクトを返すだけである。await するか、asyncio.run()asyncio.create_task() でイベントループに乗せると解決する。

よくある原因

  1. await 忘れ: foo() と書いただけでは、コルーチンオブジェクトが作られるだけで中身は動かない。
  2. 同期コードから直接呼んでいる: 通常の関数の中で await は使えないため、コルーチンが宙に浮く。
  3. スケジュールしていない: create_task()run() を通さないと、イベントループが実行する対象にならない。

解決策

1. async 関数の中では await する

import asyncio
 
async def task():
    print("done")
 
async def main():
    await task()   # await を付ける
 
asyncio.run(main())

2. 同期コードの入口では asyncio.run を使う

スクリプトのトップレベルなど await できない場所からは、イベントループを起動する。

asyncio.run(main())

3. 並行に走らせたいなら create_task

複数のコルーチンを同時に進めたいときは、タスクとしてスケジュールしてから await する。

async def main():
    t1 = asyncio.create_task(task())
    t2 = asyncio.create_task(task())
    await t1
    await t2

公式のDeveloping with asyncio(新しいタブで開く)にも、未 await のコルーチンを検出する仕組みが説明されている。

この記事は役立ちましたか?