ExceptionGroup carries multiple related exception objects, and except* selects matching leaves while retaining unmatched failures.
Python ExceptionGroup: handle selected failures and retain the rest
Operation contract
The import has a value failure and an I/O failure. An except* ValueError handler records the value failure, while the remaining OSError is re-raised in a group and caught at the surrounding boundary. This makes partial handling visible instead of flattening every failure into a success message.
Failure and ownership boundary
Except* can run several matching clauses for one raised group. It is not the same as choosing one ordinary except clause, and return, break and continue are not permitted inside its handler suites. Do not include KeyboardInterrupt or SystemExit in an ordinary ExceptionGroup; BaseExceptionGroup has a broader role. Python asyncio TaskGroup: cancel sibling work and retain failure evidence and Python exceptions: translate an input error without hiding its cause explain where grouped errors arise.
Working program
handled = []
try:
try:
raise ExceptionGroup("receipt import failures", [ValueError("quantity"), OSError("input file")])
except* ValueError as selected:
handled.extend(type(failure).__name__ for failure in selected.exceptions)
except ExceptionGroup as remaining:
print("remaining:", [type(failure).__name__ for failure in remaining.exceptions])
print("handled:", handled)Output
remaining: ['OSError']
handled: ['ValueError']Costs and limits
Matching a group inspects its exception structure and constructs selected/unmatched group views. Work scales with the contained tree, not just the number of handler clauses. Retained tracebacks can keep referenced state alive.
Common Mistakes
- A partial handler must not hide unmatched failures.
- Except* is not ordinary single-branch exception selection.
Connected lessons
Python asyncio TaskGroup: cancel sibling work and retain failure evidence, Python exceptions: translate an input error without hiding its cause, Python exception interview: chained causes and a finally return that hides failure.
Follow the ownership and update boundary
Python ExceptionGroup split: retain the nested failure structure.
