PYTHON MEBY

Pythonでコルーチンを使う(asyncio, Python 3.5以降)

この記事では、Pythonの非同期プログラミングにおけるコルーチンの使い方を解説します。asyncioライブラリを用いて、コルーチンを定義、実行し、並行処理を実現する方法を学びます。非同期処理の基本的な概念、awaitキーワード、asyncキーワード、タスクの管理方法などを具体的なコード例と共に説明します。

目次

コルーチンの基本

コルーチンは、一時停止可能な関数です。`async def`で定義します。`await`キーワードを使って、他のコルーチンの実行を待ちます。

import asyncio

async def my_coroutine():
    print('コルーチン開始')
    await asyncio.sleep(1)  # 1秒待つ
    print('コルーチン終了')

async def main():
    await my_coroutine()

asyncio.run(main())

この例では、`my_coroutine`関数は1秒間一時停止し、その後終了します。`asyncio.run()`は、コルーチンを実行するための関数です。

asyncとawaitキーワード

`async`キーワードは、関数をコルーチンとして定義するために使用します。`await`キーワードは、コルーチンの実行が完了するまで待機するために使用します。

import asyncio

async def task1():
    print('task1開始')
    await asyncio.sleep(2)
    print('task1終了')
    return 'task1の結果'

async def task2():
    print('task2開始')
    await asyncio.sleep(1)
    print('task2終了')
    return 'task2の結果'

async def main():
    result1 = await task1()
    result2 = await task2()
    print(f'task1の結果: {result1}')
    print(f'task2の結果: {result2}')

asyncio.run(main())

asyncio.run()関数

`asyncio.run()`関数は、イベントループを作成し、コルーチンを実行します。Python 3.7以降で使用可能です。

import asyncio

async def my_coroutine():
    print('Hello')
    await asyncio.sleep(1)
    print('World')

asyncio.run(my_coroutine())

タスクの並列実行

複数のタスクを並列に実行するには、`asyncio.gather()`関数を使用します。

import asyncio

async def task(name, delay):
    await asyncio.sleep(delay)
    print(f'{name}: 完了')
    return f'{name}の結果'

async def main():
    results = await asyncio.gather(
        task('A', 2),
        task('B', 1),
        task('C', 3)
    )
    print(f'結果: {results}')

asyncio.run(main())

gather関数による同時実行

`asyncio.gather()`は複数のタスクを同時に実行し、それぞれの結果をリストで返します。

import asyncio

async def my_coroutine(i):
  await asyncio.sleep(1)
  return i * 2

async def main():
  results = await asyncio.gather(my_coroutine(1), my_coroutine(2), my_coroutine(3))
  print(results) # 出力:[2, 4, 6]

asyncio.run(main())

エラー処理

try-exceptブロックを使って、コルーチン内で発生した例外を処理できます。

import asyncio

async def my_coroutine():
    try:
        await asyncio.sleep(1)
        raise Exception('エラー発生')
    except Exception as e:
        print(f'エラーキャッチ: {e}')

asyncio.run(my_coroutine())

実践例:複数のWebサイトからデータ取得

複数のWebサイトからデータを取得する例です。aiohttpライブラリが必要です。`pip install aiohttp`でインストールしてください。(aiohttpは2023年11月時点での最新版を使用してください)

import asyncio
import aiohttp

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

async def main():
    urls = ['https://www.example.com', 'https://www.google.com']
    async with aiohttp.ClientSession() as session:
        results = await asyncio.gather(*[fetch_url(session, url) for url in urls])
        for result in results:
            print(result[:100])  # 先頭100文字表示

asyncio.run(main())

関連記事