← Python トップへ / lunelukkio site
Python の async/await
作成: 2026-05-21
要約: async/await は I/O 待ち時間を有効活用するための「協調マルチタスク」の仕組み。
スレッドを使わずに複数の処理を並行して進められ、ネットワーク通信・ファイル読み書きを多数こなすプログラムで威力を発揮する。
1. なぜ async/await が必要か
通常のプログラム(同期処理)は、ファイルを読んだり HTTP リクエストを送ったりするとき、 結果が返ってくるまで その場で止まって待つ。 待っている間、CPU は何もしていない。
async/await を使うと「待つ」間に別の処理を進めることができる。 これを 非同期処理(asynchronous I/O) と呼ぶ。
図 1. 同期処理では待機時間が連続するが、非同期処理では待機中に別タスクを進める
2. 基本構文
Python の非同期処理には 3 つのキーワードを使う。
| キーワード | 意味 | 場所 |
|---|---|---|
async def |
非同期関数(コルーチン)を定義する | 関数の先頭 |
await |
「ここで待つ間、他の処理をどうぞ」と制御を手放す | async def の内部のみ |
asyncio.run() |
イベントループを起動して非同期関数を実行する | プログラムの起点(if __name__ == "__main__" 等) |
import asyncio
async def fetch_data(name: str) -> str:
# 実際は HTTP リクエストや DB クエリなどが入る
print(f"[{name}] 開始")
await asyncio.sleep(1) # "1秒待つ" のシミュレーション
print(f"[{name}] 完了")
return f"{name} のデータ"
async def main():
result = await fetch_data("A")
print(result)
asyncio.run(main())
注意:
await asyncio.sleep() は通常の time.sleep() の非同期版。
time.sleep() を async 関数内で呼ぶと、イベントループ全体がブロックされてしまう。
3. 並行実行: asyncio.gather()
上のコードは A が終わってから次へ進む(順番待ち)。
本当の並行実行には asyncio.gather() を使う。
async def main():
# 3 つを同時に開始し、全部終わるまで待つ
results = await asyncio.gather(
fetch_data("A"),
fetch_data("B"),
fetch_data("C"),
)
print(results)
# → 約 1 秒で 3 つ分完了(順次なら約 3 秒かかる)
図 2. gather() はすべてのコルーチンを同時に開始し、最後の完了を待って結果をまとめて返す
4. コルーチンとイベントループの仕組み
async def で定義した関数を呼び出すと、実際には コルーチンオブジェクト が作られるだけで実行はされない。
実行は await するか asyncio.run() に渡した時に始まる。
await を書いた箇所で、その関数はイベントループに「制御」を渡す。
イベントループは待っている処理を管理し、I/O が終わったらその処理を再開させる。
これを 協調マルチタスク と呼ぶ(OS スレッドではなく、コード自身が制御を譲り合う)。
図 3. イベントループは実行可能なコルーチンを順に実行し、await を検出したら I/O 待ちキューに移す。I/O が終わると実行可能キューに戻す
5. よくある間違い
| 状況 | NG | OK |
|---|---|---|
| 同期スリープを使う | time.sleep(1) |
await asyncio.sleep(1) |
| await を忘れる | fetch_data("A")(コルーチンオブジェクトを返すだけ) |
await fetch_data("A") |
| CPU バウンドな処理を async にする | async def で重い計算をそのまま実行 |
asyncio.to_thread() でスレッドに委譲 |
| 順番待ちになっている | await A, await B と逐次実行 |
asyncio.gather(A, B) で並行実行 |
async/await が向く場面・向かない場面
向く: HTTP クライアント、DB クエリ、ファイル I/O など I/O 待ちが多い処理
向かない: 画像処理・数値計算など CPU をフルに使う処理(この場合は multiprocessing を検討)
向く: HTTP クライアント、DB クエリ、ファイル I/O など I/O 待ちが多い処理
向かない: 画像処理・数値計算など CPU をフルに使う処理(この場合は multiprocessing を検討)