Python › Async Generators & Async Context Managers

How do you properly propagate cancellation into an async generator when the consuming task is cancelled mid-iteration?

Advanced

Answer

When the task running an 'async for' loop is cancelled, asyncio.CancelledError is raised at the current 'await' point inside the generator (typically at the yield or an internal await) — a try/finally inside the generator still runs its cleanup correctly, since CancelledError propagates through the generator's frame just like any other exception.
async def stream_data():
    try:
        while True:
            data = await fetch_next_chunk()
            yield data
    except asyncio.CancelledError:
        print("Stream cancelled, cleaning up")
        raise  # re-raise to properly propagate cancellation
    finally:
        await cleanup_connection()
Real-world example Ensuring a streaming data pipeline cleans up its network connection correctly when the consuming task is cancelled (e.g., a request timeout).

Common follow-ups: Why is it important to re-raise CancelledError rather than swallowing it inside the except block?