今回は非同期処理をPythonで実現する方法について学んでいきます。
Pythonのasync
とawait
を使うことで、複雑な非同期処理を簡単に記述でき、特にI/O処理が絡むプログラムでは大きなパフォーマンス向上が期待できます。

非同期処理ってどういうものなんでしょう?
基礎的な話から教えてもらえるとありがたいです!

「非同期処理」は、処理を待っている間に他の作業を行う処理技術です!
まずは非同期処理ついて学んだ上で、実際のプログラムや使用例を見ていきましょう!
はじめに
非同期処理とは何か?
プログラミングにおける「非同期処理」とは、ある処理を待っている間に他の作業を同時に行う技術です。
たとえば、インターネットからデータをダウンロードするような場合、ダウンロードが完了するまで何もしないのではなく、その間に他の作業を進められるようにする仕組みが非同期処理です。
Pythonでは、バージョン3.5以降、非同期処理をより簡単に扱うために、async
とawait
というキーワードが導入されました。
これらを使うことで、複雑な非同期処理をシンプルに記述できるようになっています。
Pythonで非同期処理を扱う場面
非同期処理は、特に次のような場面で活躍します。
- Webスクレイピング:複数のウェブページに同時にリクエストを送り、データを取得する。
- ネットワーク通信:チャットアプリやオンラインゲームのように、サーバーとリアルタイムでデータをやり取りする。
- I/O処理:ファイルの読み書きや、データベースからのデータ取得など、時間がかかる入出力操作を効率的に処理する。
asyncとawaitの基本的な役割
Pythonで非同期処理を行うためには、まず関数をasync
で定義し、その関数内で非同期処理が行われる部分にawait
を付けるという形が基本です。
async
:非同期関数を定義するために使用します。await
:非同期処理が終わるまで待つために使います。
次の章では、同期処理と非同期処理の違いについて、簡単な例を交えながら説明します。
同期処理と非同期処理の違い
同期処理とは
同期処理は、1つのタスクが完了するまで次のタスクが開始されない形式の処理です。
これにより、1つのタスクが完了するまで他の作業は中断されます。
たとえば、データベースに問い合わせを送った後、その結果が返ってくるまでプログラム全体が待つというイメージです。
非同期処理のメリット
一方、非同期処理は「待たない」処理です。
あるタスクが進行している間に、別のタスクを同時に進めることができます。
これにより、時間のかかる操作を効率化し、プログラム全体のパフォーマンスを向上させることが可能です。
簡単な例:同期 vs 非同期
以下は、同期処理と非同期処理の違いをシンプルに説明する例です。
同期処理の例
import time
def task():
print("Task started")
time.sleep(2) # 2秒待機
print("Task finished")
task()
print("Next task started")
このプログラムでは、task
関数が実行されると2秒間プログラムが停止し、その後に「Next task started」が表示されます。
これが同期処理です。
非同期処理の例
import asyncio
async def task():
print("Task started")
await asyncio.sleep(2) # 2秒待機
print("Task finished")
async def main():
await task()
print("Next task started")
asyncio.run(main())
非同期処理では、await
を使って2秒間の待機が発生している間に、他の処理も並行して実行できる準備が整います。await
を使うことで、プログラム全体が止まるのではなく、他の処理が行われます。
asyncとawaitの基本的な使い方
async defで非同期関数を定義
Pythonで非同期関数を定義するには、async def
という形で関数を作ります。
これによって、その関数は非同期に実行されることが期待されます。
async def example():
print("This is an async function")
この関数は非同期ですが、単独で呼び出しても何も特別なことは起こりません。
非同期関数を呼び出すときは、await
または非同期ランタイムを使用して実行する必要があります。
awaitで他の非同期処理を待つ
非同期関数の中で、他の非同期処理の完了を待つ場合には、await
を使います。
例えば、次のコードは2秒間待機してから次の処理を行います。
import asyncio
async def example():
print("Waiting for 2 seconds...")
await asyncio.sleep(2)
print("Done waiting!")
await
は、非同期関数内で時間のかかる処理が完了するのを「一時停止して待つ」ためのキーワードです。
非同期処理の例:時間を待つ処理 (asyncio.sleep)
非同期処理では、例えばasyncio.sleep()
を使って時間待機を行います。
この場合、他の処理がブロックされず、並列で処理が進むため、効率よく複数のタスクを処理することが可能です。
非同期タスクを同時に実行する
asyncio.gatherで複数の非同期処理を同時実行
複数の非同期処理を同時に実行するには、asyncio.gather()
を使用します。
これは、複数のタスクを並行して実行するのに便利な関数です。以下に実例を示します。
import asyncio
async def task_1():
print("Task 1 started")
await asyncio.sleep(2)
print("Task 1 finished")
async def task_2():
print("Task 2 started")
await asyncio.sleep(1)
print("Task 2 finished")
async def main():
await asyncio.gather(task_1(), task_2())
asyncio.run(main())
この例では、task_1
とtask_2
が同時に実行され、それぞれの処理が終了したら次の行が実行されます。task_1
は2秒待機し、task_2
は1秒待機するため、1秒後にはtask_2
が完了し、続けてtask_1
が完了するという流れになります。
実例:複数のWebリクエストを並列で行う
以下は、複数のWebリクエストを非同期に送る例です。
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
urls = ["https://example.com", "https://python.org", "https://openai.com"]
tasks = [fetch(session, url) for url in urls]
responses = await asyncio.gather(*tasks)
for response in responses:
print(response[:100]) # 最初の100文字だけ表示
asyncio.run(main())
aiohttp
というライブラリを使って、複数のURLから非同期でデータを取得しています。
これにより、ネットワーク待ち時間を無駄にせず効率的にWebリクエストを並列処理できます。
エラーハンドリングと非同期処理
非同期処理中の例外処理
非同期処理中に例外が発生した場合も、通常のPythonと同様にtry
/except
ブロックを使ってエラーハンドリングが可能です。
import asyncio
async def faulty_task():
print("Task started")
await asyncio.sleep(1)
raise ValueError("Something went wrong!")
async def main():
try:
await faulty_task()
except ValueError as e:
print(f"Error: {e}")
asyncio.run(main())
try/exceptを使ったエラーハンドリング
この例では、faulty_task
で1秒待った後にValueError
を発生させますが、main
関数内でtry
ブロックを使うことで、そのエラーをキャッチし、適切に処理しています。
まとめ
Pythonのasync
とawait
を使うことで、複雑な非同期処理を簡単に記述でき、特にI/O処理が絡むプログラムでは大きなパフォーマンス向上が期待できます。
非同期処理を使う際には、複数のタスクを同時に実行するためのasyncio.gather
や、エラーを適切に処理するためのtry
/except
といった技法も組み合わせると効果的です。
非同期処理は一度に全てを理解するのは難しいかもしれませんが、実際のプロジェクトやタスクで少しずつ使いこなすことで、その便利さと強力さを実感できるはずです。
興味がある方は、より高度な非同期プログラミングに挑戦してみてください!
このサイトのトップページへは以下へアクセス!
コメント