Python Central HubSign in

Python Programming / Python Asyncio

Timeouts and Cancellation

Use asyncio.wait_for and task cancellation to prevent hangs and handle slow I/O safely.

Why timeouts matter

Network calls can stall.

Always use timeouts to avoid:

  • stuck tasks
  • resource leaks

asyncio.wait_for

Python
import asyncio
 
 
async def slow():
    await asyncio.sleep(5)
    return "ok"
 
 
async def main():
    try:
        result = await asyncio.wait_for(slow(), timeout=1)
        print(result)
    except asyncio.TimeoutError:
        print("timed out")
 
 
asyncio.run(main())

Cancelling a task

Python
import asyncio
 
 
async def worker():
    try:
        while True:
            print("working")
            await asyncio.sleep(0.2)
    except asyncio.CancelledError:
        print("cancelled")
        raise
 
 
async def main():
    task = asyncio.create_task(worker())
    await asyncio.sleep(0.7)
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("task cancelled confirmed")
 
 
asyncio.run(main())
sketch A timeout only works if the code can be interrupted p5.js
Cancellation in asyncio is cooperative: the loop can only stop a task at an await. Three cases, all measured. A normal awaiting task under a 0.2 second timeout is cancelled on time. A task wrapped in shield survives the timeout and runs to completion even though the caller has already given up. And a blocking call with no await defeats the timeout entirely -- a 0.2 second limit around a blocking 0.8 second sleep returned after 0.80 seconds and raised nothing at all.

Best practices

  • Consider timeouts for all external calls.
  • Always handle cancellation cleanly.

Why you need a timeout

Waiting is cheap in asyncio, so it is easy to wait forever. A server that never answers will hold your task, its memory, and possibly a connection open indefinitely. A timeout turns "wait forever" into "give up after N seconds and do something sensible".

How the two examples work

wait_for(slow(), timeout=1) runs slow() but stops waiting after one second. When time runs out, asyncio cancels slow() and raises asyncio.TimeoutError to you (in Python 3.11+ this is the same as the built-in TimeoutError). That is why the example prints timed out after about one second, not five.

Cancellation works by raising asyncio.CancelledError inside the task at its current await. In cancel_task.py, the worker prints "working" about four times, is cancelled at 0.7 seconds, prints "cancelled" from its except block, and re-raises the error. Then await task in main raises CancelledError too, confirming the task really ended.

The modern style

From Python 3.11 you can also write a timeout as a block, which is handy when several awaits share one deadline:

Python
import asyncio
 
 
async def main() -> None:
    try:
        async with asyncio.timeout(0.5):
            await asyncio.sleep(0.1)
            print("step 1 done")
            await asyncio.sleep(1)  # this one exceeds the deadline
            print("step 2 done")
    except TimeoutError:
        print("gave up")
 
 
asyncio.run(main())

Only "step 1 done" and "gave up" are printed.

Common mistakes

  • Swallowing CancelledError. Catch it only to clean up (close a file, release a resource) and then raise it again. If you swallow it, the task cannot be stopped.
  • Expecting a timeout to interrupt blocking code. Cancellation only happens at an await. A time.sleep(5) cannot be interrupted. Move blocking work to asyncio.to_thread.
  • No timeout on external calls. Every network call should have one.
  • Assuming the caller giving up stops the work. With asyncio.shield, the caller gets a timeout but the inner task keeps running.

When to use it

Wrap any call to something outside your program: HTTP requests, database queries, or waiting for a message. Use task.cancel() for background tasks that should stop when the program shuts down, and always await them afterwards so their cleanup code runs.

🧪 Try It Yourself

Exercise 1 – asyncio.wait_for Timeout

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 2 – Cancel a Task

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 3 – Check Cancellation

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Was this page helpful?

Let us know how we did