サイトアイコン 【TechGrowUp】

Python開発入門54 asyncio入門!非同期処理で効率的なプログラムを作る方法

はじめに

非同期処理は、プログラムの効率を向上させるために重要な概念です。特に、ネットワーク通信やファイル入出力のようなI/Oバウンドのタスクを処理する際、非同期処理を活用することで待機時間を最小限に抑えることができます。

asyncioは、Python標準ライブラリに含まれる非同期処理を行うためのモジュールで、以下の特徴を持っています:

この記事では、asyncioの基本的な使い方から、実践的な応用例までをわかりやすく解説します。

asyncioとは

asyncioの概要

asyncioは、Pythonで非同期処理を実現するためのモジュールで、イベントループを使用してI/Oバウンドタスクを効率的に管理します。

主に以下の3つの概念が登場します:

  1. コルーチン(Coroutine)
    非同期関数の基本単位で、async defで定義されます。
  2. タスク(Task)
    コルーチンを実行可能な状態にするラッパーオブジェクトです。
  3. イベントループ(Event Loop)
    タスクをスケジュールし、実行を管理します。

asyncioの基本的な使い方

コルーチンの作成

コルーチンは、async defを使って定義します。

例:シンプルなコルーチン
import asyncio

async def greet():
    print("こんにちは!")
    await asyncio.sleep(1)
    print("非同期処理が完了しました!")

asyncio.run(greet())

説明:

複数のタスクを並行実行

複数のコルーチンを並行して実行するには、asyncio.gatherを使用します。

例:タスクの並行実行
import asyncio

async def task_1():
    print("タスク1開始")
    await asyncio.sleep(2)
    print("タスク1終了")

async def task_2():
    print("タスク2開始")
    await asyncio.sleep(1)
    print("タスク2終了")

async def main():
    await asyncio.gather(task_1(), task_2())

asyncio.run(main())

出力例:

タスク1開始  
タスク2開始  
タスク2終了  
タスク1終了  

タスクのスケジュール

asyncio.create_taskを使って、タスクをスケジュールします。

例:タスクのスケジュール
async def say_hello():
    await asyncio.sleep(1)
    print("こんにちは!")

async def main():
    task = asyncio.create_task(say_hello())
    print("タスクをスケジュールしました")
    await task

asyncio.run(main())

asyncioの応用

非同期HTTPリクエスト

非同期ライブラリaiohttpを使用して、非同期HTTPリクエストを処理します。

例:非同期HTTPリクエスト
import aiohttp
import asyncio

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print(f"URL: {url}, ステータス: {response.status}")
            return await response.text()

async def main():
    urls = ["https://example.com", "https://python.org"]
    await asyncio.gather(*(fetch(url) for url in urls))

asyncio.run(main())

非同期でデータを処理

非同期I/O操作を行いながら、データを逐次処理します。

例:非同期データ処理
async def process_data(data):
    print(f"処理中: {data}")
    await asyncio.sleep(1)
    print(f"処理完了: {data}")

async def main():
    data_list = [1, 2, 3, 4, 5]
    await asyncio.gather(*(process_data(data) for data in data_list))

asyncio.run(main())

タイムアウト処理

非同期タスクにタイムアウトを設定する方法を紹介します。

例:タイムアウトの設定
import asyncio

async def long_task():
    await asyncio.sleep(5)
    print("タスク完了")

async def main():
    try:
        await asyncio.wait_for(long_task(), timeout=3)
    except asyncio.TimeoutError:
        print("タイムアウトしました")

asyncio.run(main())

asyncioを使う際の注意点

  1. CPUバウンドタスクには非適切
    asyncioはI/Oバウンドタスクに最適化されています。CPUバウンドタスクにはmultiprocessingを検討しましょう。
  2. エラーハンドリングの実装
    タスクの実行中に発生するエラーを適切に処理することが重要です。
  3. イベントループの管理
    一度に複数のイベントループを作成しないよう注意しましょう。

まとめ

asyncioは、Pythonで非同期処理を実現するための強力なモジュールです。イベントループやタスクの仕組みを理解することで、効率的なプログラムを構築できます。この記事で紹介した基本から応用例を活用し、非同期プログラミングのスキルを磨いてみてください!

モバイルバージョンを終了