Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python concurrency interview: cancellation must still run cleanup

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

Asyncio task cancellation requests that a task raise CancelledError at a suspension point, allowing its finally cleanup to run.

Download Python source kit

Operation contract

The owned worker signals that it has started, then waits on an event that the test never releases. The caller cancels it and awaits the result. Cleanup records a release marker before the caller observes CancelledError. No timing sleep is used to guess whether the worker reached its suspension point; the start event defines that boundary.

Failure and ownership boundary

Cancellation is cooperative. Code that blocks the event-loop thread or suppresses cancellation can violate the caller’s expectations. Releasing a local marker is not proof that an external service canceled a request. Python asyncio timeout: cancellation and cleanup ownership and Python asyncio TaskGroup: cancel sibling work and retain failure evidence address related caller/worker coordination.

Working program

python
import asyncio

async def inspect_cancellation():
    started = asyncio.Event()
    never_released = asyncio.Event()
    cleanup = []
    async def worker():
        try:
            started.set()
            await never_released.wait()
        finally:
            cleanup.append("released")
    task = asyncio.create_task(worker())
    await started.wait()
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("caller observed cancellation")
    print("cleanup:", cleanup)
    print("task finished:", task.done())

asyncio.run(inspect_cancellation())

Output

Output
caller observed cancellation
cleanup: ['released']
task finished: True

Costs and limits

The fixture owns one task and two event objects. Cancellation latency depends on scheduling and the next suspension point, not a fixed wall-clock guarantee. A retained unawaited task can keep reachable state alive after the caller’s surrounding function returns.

Common Mistakes

  • Await the canceled task so cleanup and failure become observable.
  • Use a synchronization event instead of guessing task state with a sleep.

Connected lessons

Python asyncio timeout: cancellation and cleanup ownership, Python asyncio TaskGroup: cancel sibling work and retain failure evidence, Python ContextVar: task-local labels without sharing one global binding.

Follow the service contract

Python cancellation review: release a permit before propagating task cancellation.

python
concurrency-interview
Storage details