Python の asyncio.Task と Future の違い

asyncio.Task と asyncio.Future は非同期処理の基盤となるオブジェクトです。似ていますが、役割が異なります。

Future:将来の結果を表す

Future は「まだ完了していない計算の結果」を表すプレースホルダーです。

import asyncio

async def main():
    loop = asyncio.get_event_loop()
    future = loop.create_future()
    
    print(future.done())  # False
    
    future.set_result(42)
    
    print(future.done())   # True
    print(future.result()) # 42

asyncio.run(main())

Future は低レベル API で、通常は直接使いません。

Task:コルーチンをラップした Future

Task は Future のサブクラスで、コルーチンを実行してその結果を Future として提供します。

import asyncio

async def fetch_data():
    await asyncio.sleep(1)
    return "data"

async def main():
    task = asyncio.create_task(fetch_data())
    
    print(type(task))      # <class '_asyncio.Task'>
    print(task.done())     # False
    
    result = await task
    print(result)          # data
    print(task.done())     # True

asyncio.run(main())

主な違い

Future

結果のプレースホルダー。外部から set_result() で結果を設定する。低レベル API。

Task

コルーチンを実行する。コルーチンの完了時に自動で結果が設定される。高レベル API。

Task のキャンセル

import asyncio

async def long_running():
    try:
        await asyncio.sleep(10)
    except asyncio.CancelledError:
        print("Task was cancelled")
        raise

async def main():
    task = asyncio.create_task(long_running())
    await asyncio.sleep(0.1)
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("Caught cancellation")

asyncio.run(main())

複数の Task を管理

async def main():
    tasks = [
        asyncio.create_task(fetch_data()),
        asyncio.create_task(fetch_data()),
    ]
    results = await asyncio.gather(*tasks)

日常的な非同期プログラミングでは Task を使い、Future はライブラリ開発など低レベルな場面で使います。