Python 3.11's TaskGroup and ExceptionGroup bring structured concurrency to asyncio. Master TaskGroups, ExceptionGroup handling with except*, anyio for backend-agnostic code, cancellation scopes, and asyncio.shield for building robust, composable async applications.
0 / 5 completed
1 / 5
Python 3.11 introduced asyncio.TaskGroup. A developer uses it as async with asyncio.TaskGroup() as tg: tg.create_task(task_a()); tg.create_task(task_b()). What happens if task_a() raises an exception?
In asyncio.TaskGroup, if any task raises an exception, all remaining tasks are cancelled, and the context manager raises an ExceptionGroup (Python 3.11+) containing all exceptions from failed tasks. This is structured concurrency: tasks form a scope, and the scope doesn't exit until all tasks complete or all are cancelled.
2 / 5
Python 3.11 added ExceptionGroup. A developer uses except* ValueError as eg. What does the except* syntax do?
except* is a new Python 3.11 syntax for handling ExceptionGroups. It matches all exceptions of the specified type within the group (even nested groups), collects them in eg.exceptions, and allows the handler to process them. Unmatched exception types in the group propagate. This enables handling individual error types from parallel task failures.
3 / 5
A developer uses anyio with async with anyio.create_task_group() as tg. What is anyio's primary value over using asyncio's TaskGroup directly?
anyio provides a compatibility layer over both asyncio and trio backends. Code written with anyio.create_task_group(), anyio.sleep(), etc. runs unchanged on either backend. Libraries like FastAPI and Starlette use anyio to remain backend-agnostic, letting users choose their preferred async runtime.
4 / 5
In structured concurrency with asyncio TaskGroup, what is meant by a task's cancellation scope?
A cancellation scope defines the boundary within which tasks can be cancelled. In structured concurrency, a TaskGroup forms an implicit cancellation scope: when the group is cancelled (or a task fails), all tasks within the scope receive cancellation. anyio's move_on_after() and fail_after() create explicit timeout-based cancellation scopes.
5 / 5
A developer uses asyncio.shield(coro()) inside a TaskGroup. What does asyncio.shield() protect against?
asyncio.shield() wraps a coroutine so that external cancellation of the awaiting task does not propagate into the shielded coroutine. The inner coroutine continues running even if the outer context is cancelled. However, if the shielded task itself is explicitly cancelled, it will be cancelled. This is useful for cleanup operations that must complete even during cancellation.