TaskGroups & structured concurrency

P33.structured-concurrency.01 · Audience: guest, it-ml, language-pro · Prerequisites: Tasks, gather & timeouts

Real LLM grading for this pageLLM grading (this page):

gather runs tasks, but it leaks them on failure: if one coroutine raises, the others keep running, orphaned. asyncio.TaskGroup (Python 3.11+) makes concurrent work behave like a function call — it does not return until every task is done, and a failure cancels the siblings. The kernel rung runs real TaskGroups.

Step 1 / 2Concurrency needs a lifetime
ⓘ Concept: A scope tasks cannot outlive
async with asyncio.TaskGroup() as tg: is a scope. Tasks you start with tg.create_task(...) are all awaited before the block exits — so concurrent work has the same lifetime as the block, exactly like local variables. Nothing leaks past it.

Why it matters — Leaked background tasks are a classic async bug — they run after the code that started them has moved on, holding resources and hiding errors.

Ask the mentor about this module

Ask a question about this content. The mentor explains and grounds its answer in what you are studying; asking is recorded as a learning signal, not a grade.

Ctrl/Cmd + Enter to send

🎓 Practice ladder

2 graded rungs · ~22 min

Run tasks under a real TaskGroup on the kernel, then explain why structured concurrency beats a bag of loose futures.

Rung 1 — run tasks under a TaskGroup (kernel)

Loading exercise…

Rung 2 — why structured concurrency? (interview)

Loading exercise…

Structured concurrency keeps async code honest. The last track handles the moment async meets the blocking, CPU-bound world — without freezing the loop.