Pythonでコルーチンのネストとコンポジションを理解しよう

この記事では、Pythonのコルーチンにおける「ネスト(入れ子)」と「コンポジション」に焦点を当てます。具体的なコード例とその解説、応用例を含めて解説を進めていきます。

目次

コルーチンとは?

コルーチンは、一時停止と再開が可能な特殊な関数です。ジェネレータを一般化したものとも言われます。通常の関数が一度呼び出されると最後まで処理が進むのに対し、コルーチンは途中で一時停止し、後から再開することができます。

ネストとコンポジションの基本

ネスト(Nested Coroutines)

ネストとは、一つのコルーチンの中で別のコルーチンを呼び出すことです。

# コルーチンのネスト例
async def coro1():
    print("coro1: start")
    await coro2()  # coro2を呼び出す
    print("coro1: end")

async def coro2():
    print("coro2: called")

コンポジション(Coroutine Composition)

複数のコルーチンを組み合わせて一つのタスクを構成することを指します。

# コンポジション例
async def main():
    task1 = asyncio.create_task(coro1())
    task2 = asyncio.create_task(coro2())
    await task1
    await task2

コルーチンのネスト:詳細解説

yield fromの使用

Python 3.3以前では、ジェネレータベースのコルーチンでは`yield from`を使ってネストを行います。

# yield fromの使用例
def coro1():
    yield "coro1: start"
    yield from coro2()
    yield "coro1: end"

def coro2():
    yield "coro2: called"

yield fromの挙動

`yield from`は内部のコルーチン(coro2)が終了するまで、外部のコルーチン(coro1)を一時停止させます。

応用例1:非同期I/O処理

非同期I/O処理でファイルの読み書きを行いましょう。

import asyncio

async def read_file(file_path):
    print(f"Reading {file_path}")
    await asyncio.sleep(1)
    print(f"Read {file_path}")

async def write_file(file_path):
    print(f"Writing {file_path}")
    await asyncio.sleep(1)
    print(f"Wrote {file_path}")

async def io_tasks():
    await asyncio.gather(read_file("file1.txt"), write_file("file2.txt"))

応用例2:複数APIへの非同期リクエスト

複数のAPIエンドポイントに非同期でリクエストを送信します。

import aiohttp
import asyncio

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def multiple_requests():
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, f"https://api.example.com/data/{i}") for i in range(5)]
        return await asyncio.gather(*tasks)

まとめ

Pythonのコルーチンにおけるネストとコンポジションについて、基本から応用までを解説しました。これらの概念を理解することで、非同期プログラミングの可能性が広がります。ぜひ実際のコードで試してみてください。

コメント

コメントする

目次