Timeouts, cancellation, shield
advanced22 min readLesson 127 of 169
Bound waiting time; keep cleanup cancellation-safe; never swallow CancelledError.
Timeouts and cancellation, done properly
Cancellation in asyncio is cooperative and exception-based: cancelling a
task arranges CancelledError to be raised at its current await point.
asyncio.timeout(seconds) (3.11+) wraps a block:
import asyncio
async def slow_api():
await asyncio.sleep(10)
async def handler():
try:
async with asyncio.timeout(0.5):
await slow_api()
except TimeoutError:
return "gave up" # TimeoutError in 3.11+, asyncio.TimeoutError before
What professionals must know:
- Timeouts cancel; cancellation propagates. Inner
finallyblocks and async context managers still run โ cleanup code must be cancellation-safe (no unbounded awaits inside cleanup). - A coroutine may shield a critical section with
asyncio.shield(coro)โ the shielded await still gets CancelledError in the caller, but the inner operation continues. - Swallowing
CancelledError(bareexcept Exceptiondoes NOT catch it in 3.8+... butexcept BaseExceptiondoes) is the classic way to break structured concurrency. Only catch it to re-raise after cleanup. asyncio.call_later, loop-bound timers, andasyncio.to_thread(3.9+) for offloading blocking calls to a thread round out the toolkit.