1. はじめに
Pythonには、複数の処理を効率よく同時に実行するための非同期処理があります。本記事では、Pythonの非同期処理を実現する標準ライブラリasyncio
の基本から応用までを、初心者向けにわかりやすく解説します。
Python|非同期処理:asyncioを使うことで、ファイル操作やネットワーク通信などの時間がかかる処理でも、スムーズなプログラム実行が可能になります。
「複数の処理を並列的に進めたい」「待ち時間がある処理を効率化したい」といったニーズに応える、Python標準の非同期処理機構をこの記事でマスターしましょう。
2. asyncioとは?非同期処理の基本と書き方
2-1. 非同期処理とは?
非同期処理(Asynchronous Programming)とは、ある処理が完了するのを待たずに、他の処理を同時に進めるプログラミング手法です。これにより、待ち時間(I/O待ちなど)を無駄にせず、効率的な実行が可能になります。
2-2. asyncioの基本構文
Pythonのasyncio
では、非同期関数をasync def
で定義し、処理の途中で待機させるにはawait
を使います。以下に簡単な例を紹介します。
import asyncio
# 非同期関数の定義
async def say_hello():
print("Hello...")
await asyncio.sleep(2) # 2秒待機
print("...World!")
# 非同期関数の実行
asyncio.run(say_hello())
実行結果:
Hello...
...World!
この例では、say_hello
関数内で2秒間の待機を挟みながら、処理を中断せずに進めています。
3. よくある使い方・応用例
3-1. 複数のタスクを同時実行する
asyncio
の強力な機能の一つが「複数タスクの同時実行」です。asyncio.gather()
を使えば、複数の非同期関数を同時に走らせることができます。
import asyncio
async def task(name, sec):
print(f"Start {name}")
await asyncio.sleep(sec)
print(f"End {name} after {sec} seconds")
async def main():
await asyncio.gather(
task("Task A", 2),
task("Task B", 3)
)
asyncio.run(main())
実行結果:
Start Task A
Start Task B
End Task A after 2 seconds
End Task B after 3 seconds
このように、各タスクの待機時間が重なり、全体の実行時間が短縮されます。
3-2. WebクローリングやAPI取得に活用
非同期処理は、APIから複数データを取得するような処理に最適です。以下はダミーのAPI取得を模した例です。
import asyncio
async def fetch_data(i):
print(f"Fetching data {i}...")
await asyncio.sleep(1)
print(f"Done fetching data {i}")
return f"data_{i}"
async def main():
results = await asyncio.gather(*(fetch_data(i) for i in range(5)))
print("All data:", results)
asyncio.run(main())
実行結果:
Fetching data 0...
Fetching data 1...
Fetching data 2...
Fetching data 3...
Fetching data 4...
Done fetching data 0
Done fetching data 1
Done fetching data 2
Done fetching data 3
Done fetching data 4
All data: ['data_0', 'data_1', 'data_2', 'data_3', 'data_4']
複数APIを同時取得するWebアプリやクローラでは、実用性が高いパターンです。
4. asyncioを使う上での注意点・エラー対策
4-1. 非同期関数を呼び出すにはawaitが必要
非同期関数(async def
で定義)は、await
を使って呼び出す必要があります。通常の関数から呼び出すと、下記のようなエラーになります。
RuntimeWarning: coroutine 'xxx' was never awaited
対処法: await 関数名()
で呼び出すか、asyncio.run()
でラップしましょう。
4-2. asyncio.run()は1度だけ
asyncio.run()
は、スクリプト全体で1回だけ使うのが基本です。Jupyter Notebookなどではawait 関数()
で直接実行することが推奨されます。
4-3. ブロッキング処理との併用に注意
time.sleep()
などの通常の同期関数を使うと、非同期処理がブロックされてしまいます。代わりにawait asyncio.sleep()
など非同期版を使用してください。
5. まとめ
本記事ではPythonの非同期処理「asyncio」について、基本構文から応用例までを紹介しました。
async def
とawait
を使って非同期関数を定義・実行できるasyncio.gather()
を使えば複数タスクの同時処理が可能- API取得や時間のかかる処理で活用できる
非同期処理は少し難しく感じるかもしれませんが、「I/O処理の最適化」や「複数タスクの同時処理」が求められる場面では大きな武器になります。特にWeb開発・スクレイピング・チャットボット開発などでは必須の知識です。
ぜひ、この記事をきっかけにasyncio
を活用した効率的なPythonプログラミングにチャレンジしてみてください!