Giving child tasks an explicit scope

Starting concurrent work without managing its lifetime can let a caller finish while background activities retain resources or fail unnoticed. Structured concurrency organizes such work within lifetime boundaries that also define waiting and termination responsibilities.

Python TaskGroup provides one concrete form: tasks enter an asynchronous context, and leaving that context waits for the group’s tasks. This establishes a managed containment relationship rather than merely collecting task references in an ordinary list.

References: [1]

Coordinating peers when a task fails

When a Python TaskGroup member fails with a non-cancellation exception, the remaining tasks are cancelled and relevant failures are reported after cleanup. This differs from launching independent work and waiting for just one result.

The interface normally preserves multiple failures through an ExceptionGroup or related grouping, with special treatment for KeyboardInterrupt and SystemExit. The concrete rules determine whether peers continue and when the caller obtains the final failure report.

References: [1]

Lifetime management still needs cooperation

Cancellation commonly depends on task execution cooperating. Swallowing CancelledError can disrupt coordination used internally by TaskGroup, so cleanup must preserve the appropriate control flow rather than indiscriminately hiding exceptions.

Structured lifetimes do not automatically provide parallel processors, business rollback, or synchronization of shared data. Workload limits and resource contracts remain necessary. The abstraction organizes how related concurrent work is started, awaited, and brought to completion.

References: [1] [2]