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

Python asyncio TaskGroup: cancel sibling work and retain failure evidence

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A TaskGroup owns asynchronous child tasks and waits for them to finish or be cancelled when its scope exits.

Download Python source kit

Operation contract

The receipt import starts one waiting worker and one worker that fails after yielding control. The failure cancels the waiting sibling, whose finally block records cleanup. The caller catches the ValueError part of the resulting exception group and prints stable evidence rather than relying on task completion order.

Failure and ownership boundary

Cancellation is cooperative: code must reach an await boundary and must not swallow cancellation merely to continue work. Cancelling a coroutine does not undo a database commit or a payment already performed. This fixture has no network I/O and uses a finally marker, not a claim about closing a production client. Python context managers: clean up on success and failure stays separate from scheduling.

Working program

python
import asyncio

async def import_batch():
    events = []
    started = asyncio.Event()
    async def waiting_import():
        started.set()
        try:
            await asyncio.Event().wait()
        finally:
            events.append("sibling cleaned")
    async def failed_import():
        await started.wait()
        raise ValueError("invalid receipt")
    try:
        async with asyncio.TaskGroup() as tasks:
            tasks.create_task(waiting_import())
            tasks.create_task(failed_import())
    except* ValueError:
        events.append("failure observed")
    print(events)

if __name__ == "__main__":
    asyncio.run(import_batch())

Output

Output
['sibling cleaned', 'failure observed']

Costs and limits

The group retains two tasks and their exception state. Creating one task per unbounded input still grows memory with input count; TaskGroup itself is not an admission limit.

Common Mistakes

  • Do not hide cancellation to keep failed sibling work running.
  • Task ownership does not create a task-count limit.

Connected lessons

Python context managers: clean up on success and failure, Python thread pools: collect results and observe worker failures, Java cancellation: timed waits and cooperative interruption.

Apply this boundary

Python asyncio.Queue: backpressure and completion accounting, Python asyncio timeout: cancellation and cleanup ownership.

Follow the related contract

Python ContextVar: task-local labels without sharing one global binding, Python concurrency interview: cancellation must still run cleanup.

Trace the related workflow

Python asyncio.gather: a sibling can continue after the first failure.

Related boundary

Python asyncio Semaphore: bound active work, not queued tasks

Continue with Python ContextVar tasks: capture request context at task creation.

Continue with Python asyncio call graphs: inspect a live task without retaining frames.

python
async-task-groups
Storage details