コンテンツにスキップ

Python/非同期関数

出典: フリー教科書『ウィキブックス(Wikibooks)』

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(): 非同期関数を実行するための便利な関数。内部でイベントループを管理します。

非同期関数の特徴

[編集]
  1. 非ブロッキング処理
    • awaitを使うことで、I/O操作中に他のタスクを実行できます。
    • 例えば、ネットワークリクエスト中に別のリクエストを処理できます。
  2. 並行処理
    • 複数の非同期関数を並行して実行できます。
    • 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())
    
  3. コルーチン
    • 非同期関数はコルーチンを返します。コルーチンは、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は、非同期ファイル操作を行うためのライブラリです。

非同期関数の注意点

[編集]
  1. ブロッキングコードの回避
    • 非同期関数内でブロッキングコード(例: time.sleep())を使うと、非同期処理のメリットが失われます。
    • 代わりに、await asyncio.sleep()を使います。
  2. イベントループの管理
    • 非同期関数は、イベントループがないと実行できません。
    • asyncio.run()を使うか、手動でイベントループを作成する必要があります。
  3. スレッドセーフではない
    • 非同期関数は、シングルスレッドで動作するため、スレッドセーフではありません。
    • マルチスレッド環境では注意が必要です。

まとめ

[編集]
  • 非同期関数は、async defで定義され、awaitを使って非同期処理を待機します。
  • 非同期関数は、I/Oバウンドなタスクを効率的に処理するために使用されます。
  • イベントループ(asyncio.run())を使って実行します。
  • 非同期関数を使うことで、並行処理や非ブロッキング処理を実現できます。

非同期関数を活用することで、高性能でスケーラブルなアプリケーションを開発できます。