Python › Exception Handling

How does Python 3.11's exception groups (ExceptionGroup) and the 'except*' syntax let you handle MULTIPLE unrelated exceptions raised together?

Advanced

Answer

ExceptionGroup wraps multiple exceptions raised together (common in concurrent code, like asyncio.gather with multiple failures) as a single object; 'except*' matches and handles the SUBSET of exceptions within the group matching a given type, potentially re-raising a NEW ExceptionGroup with the remaining unmatched ones.
try:
    raise ExceptionGroup("multiple failures", [ValueError("bad value"), TypeError("bad type")])
except* ValueError as eg:
    print(f"Handled ValueErrors: {eg.exceptions}")
except* TypeError as eg:
    print(f"Handled TypeErrors: {eg.exceptions}")
Real-world example Handling multiple independent failures from concurrent tasks (like several parallel API calls) that fail simultaneously with different exception types.

Common follow-ups: How does asyncio.gather() (or TaskGroup in 3.11+) actually produce an ExceptionGroup from multiple failed concurrent tasks?