patternpythonnoneModerate
ExceptionGroup and except* for Handling Multiple Exceptions
Viewed 0 times
Python 3.11+
ExceptionGroupexcept*TaskGroupmultiple exceptionsasyncioPEP 654
Error Messages
Problem
When multiple async tasks fail simultaneously via asyncio.TaskGroup, only the first exception was surfaced previously. Multiple concurrent failures were lost or required ugly workarounds.
Solution
Use ExceptionGroup and except* to handle multiple simultaneous exceptions.
import asyncio
async def failing_task(name: str, should_fail: bool) -> str:
await asyncio.sleep(0.1)
if should_fail:
raise ValueError(f'{name} failed')
return name
async def main():
try:
async with asyncio.TaskGroup() as tg:
t1 = tg.create_task(failing_task('a', True))
t2 = tg.create_task(failing_task('b', False))
t3 = tg.create_task(failing_task('c', True))
# t1 and t3 both fail — ExceptionGroup raised with both errors
except* ValueError as eg:
for exc in eg.exceptions:
print(f'Caught: {exc}')
except* TypeError as eg:
print(f'Type errors: {eg.exceptions}')
# Manual ExceptionGroup
def process_all(items: list) -> None:
errors = []
for item in items:
try:
process(item)
except Exception as e:
errors.append(e)
if errors:
raise ExceptionGroup('Processing errors', errors)Why
asyncio.TaskGroup collects all task exceptions and raises them as an ExceptionGroup. The except* syntax filters ExceptionGroups by exception type, allowing each type to be handled separately.
Gotchas
- except can only catch ExceptionGroup — not bare exceptions. Cannot mix except and except in the same try block.
- except* handlers receive an ExceptionGroup, not a single exception — iterate eg.exceptions.
- Nested ExceptionGroups are flattened for except* matching.
Revisions (0)
No revisions yet.