Python/非同期関数
表示
< Python
Pythonの非同期関数(Asynchronous-function)は、非同期プログラミングを実現するための重要な要素です。非同期関数を使用することで、I/Oバウンドなタスク(ネットワークリクエスト、ファイル読み書きなど)を効率的に処理できます。以下に、非同期関数の基本的な概念と使い方を解説します。
非同期関数とは?
[編集]非同期関数は、async def
で定義される関数で、非同期処理を行うためのものです。通常の関数と異なり、非同期関数は実行時に「コルーチン」を返します。コルーチンは、実行を一時停止し、後で再開できる特殊なオブジェクトです。
非同期関数は、await
キーワードを使って、他の非同期関数や非同期操作の完了を待機します。これにより、ブロッキングせずに並行処理を実現できます。
非同期関数の定義
[編集]非同期関数は、async def
を使って定義します。
from asyncio import sleep async def my_async_function(): print("Start") await sleep(1) # 非同期処理の例 print("End")
async def
: 非同期関数を定義するためのキーワード。await
: 非同期処理の完了を待機するためのキーワード。
非同期関数の実行
[編集]非同期関数は、直接呼び出しても実行されません。代わりに、イベントループを使って実行する必要があります。Pythonでは、asyncio
モジュールがイベントループを提供します。
例: 非同期関数の実行
[編集]from asyncio import sleep, run async def my_async_function(): print("Start") await sleep(1) # 1秒待機 print("End") # イベントループで実行 run(my_async_function())
asyncio::run()
: 非同期関数を実行するための便利な関数。内部でイベントループを管理します。
非同期関数の特徴
[編集]- 非ブロッキング処理
await
を使うことで、I/O操作中に他のタスクを実行できます。- 例えば、ネットワークリクエスト中に別のリクエストを処理できます。
- 並行処理
- 複数の非同期関数を並行して実行できます。
asyncio.gather()
を使うと、複数の非同期タスクを同時に実行できます。
from asyncio import sleep, gather, run async def task1(): await sleep(1) print("Task 1 done") async def task2(): await sleep(2) print("Task 2 done") async def main(): await gather(task1(), task2()) run(main())
- コルーチン
- 非同期関数はコルーチンを返します。コルーチンは、
await
で実行されるまで待機状態になります。
- 非同期関数はコルーチンを返します。コルーチンは、
非同期関数の使用例
[編集]例1: 非同期HTTPリクエスト
[編集]from aiohttp import ClientSession from asyncio import run async def fetch(url): async with ClientSession() as session: async with session.get(url) as response: return await response.text() async def main(): url = "https://example.com" html = await fetch(url) print(html) run(main())
aiohttp
は、非同期HTTPリクエストを行うためのライブラリです。
例2: 非同期ファイル読み書き
[編集]from aiofiles import open from asyncio import run async def read_file(filename): async with open(filename, mode='r') as f: content = await f.read() return content async def main(): content = await read_file("example.txt") print(content) run(main())
aiofiles
は、非同期ファイル操作を行うためのライブラリです。
非同期関数の注意点
[編集]- ブロッキングコードの回避
- 非同期関数内でブロッキングコード(例:
time.sleep()
)を使うと、非同期処理のメリットが失われます。 - 代わりに、
await asyncio.sleep()
を使います。
- 非同期関数内でブロッキングコード(例:
- イベントループの管理
- 非同期関数は、イベントループがないと実行できません。
asyncio.run()
を使うか、手動でイベントループを作成する必要があります。
- スレッドセーフではない
- 非同期関数は、シングルスレッドで動作するため、スレッドセーフではありません。
- マルチスレッド環境では注意が必要です。
まとめ
[編集]- 非同期関数は、
async def
で定義され、await
を使って非同期処理を待機します。 - 非同期関数は、I/Oバウンドなタスクを効率的に処理するために使用されます。
- イベントループ(
asyncio.run()
)を使って実行します。 - 非同期関数を使うことで、並行処理や非ブロッキング処理を実現できます。
非同期関数を活用することで、高性能でスケーラブルなアプリケーションを開発できます。