Python asyncio実践ガイド:並行処理で処理速度を10倍にする具体的テクニック
はじめに Pythonで大量のAPI呼び出しやファイル操作を行う際、処理時間がボトルネックになることは珍しくありません。同期的な処理では、一つの操作が完了するまで次の処理を開始できないため、I/O待ち時間が積み重なってしまいます。 本記事では、Pythonのasyncioモジュールを使った非同期プログラミングについて、基礎概念から実践的なパターンまでを体系的に解説します。実際のプロジェクトで使える具体的なコード例を通じて、処理速度を劇的に改善する方法を学んでいきましょう。 asyncioの基本概念 イベントループとは asyncioの中心にあるのがイベントループです。イベントループは、非同期タスクの実行を管理し、I/O操作の完了を監視して、適切なタイミングでタスクを再開させる役割を担います。 1 2 3 4 5 6 7 8 9 import asyncio async def main(): print("Hello") await asyncio.sleep(1) print("World") # Python 3.7以降の推奨方法 asyncio.run(main()) async/awaitの仕組み async defで定義された関数はコルーチン関数となり、呼び出すとコルーチンオブジェクトを返します。awaitキーワードを使うことで、そのコルーチンの完了を待機しつつ、その間に他のタスクを実行できるようになります。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import asyncio import aiohttp async def fetch_url(session: aiohttp.ClientSession, url: str) -> dict: """URLからデータを非同期で取得""" async with session.get(url) as response: return { "url": url, "status": response.status, "content_length": len(await response.text()) } async def main(): urls = [ "https://api.github.com", "https://api.stripe.com", "https://api.openai.com" ] async with aiohttp.ClientSession() as session: # 全URLを並行して取得 tasks = [fetch_url(session, url) for url in urls] results = await asyncio.gather(*tasks) for result in results: print(f"{result['url']}: {result['status']}") asyncio.run(main()) 実践パターン1:大量のAPI呼び出しを高速化 問題:同期処理での遅延 例えば、1000件のユーザーデータをAPIから取得する場合を考えます。1リクエストあたり100msかかるとすると、同期処理では100秒もの時間が必要です。 ...