exceptiongroup
A backport of Python 3.11's BaseExceptionGroup and ExceptionGroup classes, letting older Python versions catch and format grouped exceptions.
Repository Health
Technical Analysis
exceptiongroup backports the BaseExceptionGroup and ExceptionGroup classes introduced by PEP 654 in Python 3.11, along with a catch() helper for dispatching handlers across grouped exceptions on versions that lack the native except* syntax. It also ships a backport of Python 3.12.1’s contextlib.suppress() that understands exception groups, and patches traceback.TracebackException plus sys.excepthook so unhandled exception groups print correctly on older interpreters.
On Python 3.11 and later the package steps out of the way entirely: it re-exports the built-in classes and traceback functions instead of the backported versions, and skips the monkey-patching altogether. This makes it safe to depend on unconditionally across a wide version range, which is why it has become a common transitive dependency for libraries like pytest and anyio that need exception-group semantics on Python 3.7–3.10.
What You Get
BaseExceptionGroupandExceptionGroupclasses withsubgroup(),split(), andderive()methods matching the CPython 3.11 implementation- A
catch()context manager for dispatching different exception types (even nested inside groups) to separate handler callables withoutexcept*syntax - A backport of
contextlib.suppress()from Python 3.12.1 that correctly suppresses exceptions nested inside exception groups - Monkey-patched
TracebackExceptionand an installedsys.excepthookso unhandled exception groups format correctly in tracebacks on pre-3.11 Python - Drop-in versions of
traceback.format_exception(),format_exception_only(),print_exception(), andprint_exc()that render exception groups even when monkey patching is blocked
Common Use Cases
- Libraries that need to raise and match exception groups (e.g. from concurrent task groups) while still supporting Python 3.7–3.10
- Applications catching multiple unrelated exception types raised by parallel operations and handling each type differently via
catch() - Test suites and frameworks (pytest, anyio) that rely on exception-group semantics as a transitive dependency across the full supported Python range
- Code that wants correctly formatted tracebacks for exception groups without waiting for users to upgrade to Python 3.11
- Selectively suppressing specific exception types that may be wrapped inside an exception group, via the backported
suppress()
Under The Hood
Architecture
exceptiongroup is a small single-purpose backport structured as flat modules under src/exceptiongroup/: __init__.py conditionally imports either the stdlib’s native BaseExceptionGroup/ExceptionGroup (Python 3.11+) or the pure-Python implementations in _exceptions.py, chooses contextlib.suppress versus the local _suppress.py backport based on a Python 3.12.1 version check, and installs traceback monkey-patching from _formatting.py plus a sys.excepthook only when running on Python <3.11 and no other hook is already present (guarded by the EXCEPTIONGROUP_NO_PATCH env var). The core abstraction is _exceptions.BaseExceptionGroup, which reimplements CPython’s __new__/subgroup/split/derive semantics for grouping and filtering exceptions, and _catch.py builds a context manager (_Catcher) on top of split() to dispatch grouped exceptions to per-type handler callables — every other module is written against that exact return contract, making it the piece that would break everything else if changed.
Tech Stack
Pure Python 3.7+ with no runtime dependencies beyond typing_extensions>=4.6.0 (only on Python <3.13, for TypeVar defaults), built with flit_scm as the PEP 517 backend and setuptools_scm for version derivation. Testing uses pytest>=6 matrixed across Python 3.7–3.14 and PyPy3 via tox, with a separate “typing” tox environment running pyright and mypy against tests/check_types.py. Linting and formatting are enforced by ruff (including isort, pyupgrade, and flake8-implicit-str-concat rules) through pre-commit, and releases publish to PyPI via a tag-triggered GitHub Actions workflow using pypa/gh-action-pypi-publish with OIDC trusted publishing.
Code Quality
The test suite spans several thousand lines across test_exceptions.py, test_formatting.py, test_catch.py, test_catch_py311.py, and test_suppress.py, exercising both the native (3.11+) and backported code paths, plus subprocess-based tests for apport excepthook integration. Error handling is explicit — the constructor raises TypeError/ValueError with specific messages for invalid arguments (non-string message, empty exception sequence, nesting a BaseException inside an ExceptionGroup) rather than swallowing bad input. Naming is consistent snake_case with underscore-prefixed private modules; type hints are comprehensive and verified in CI via pyright/mypy, and the package ships a py.typed marker.
What Makes It Unique
This is a backport, not a novel design — its value is faithfully reproducing PEP 654 semantics on Python versions that predate the stdlib feature, then getting out of the way entirely on 3.11+. Its one genuinely useful addition beyond a plain backport is the monkey-patched TracebackException and installed exception hook that make ungrouped tracebacks print correctly on old Pythons, plus the catch() context-manager sugar for exception dispatch without except* syntax. Not technically novel, but a well-scoped compatibility shim relied on transitively by widely-used libraries.
Used by 4 apps in this directory
argilla
AI Development · Data Engineering
Collaborate on high-quality AI training data with a self-hosted annotation platform built for LLMs, NLP, and multimodal models.
ClickHouse
Databases · Analytics · Data Engineering
Open-source column-oriented database that delivers real-time analytical queries on petabyte-scale data with millisecond latency.
marimo
Developer Tools · Data Engineering
A reactive Python notebook that eliminates hidden state, runs reproducibly, and deploys as a web app or script — stored as pure Python, built for the AI era.
Promptfoo
AI Development
An open-source CLI and library for evaluating and red-teaming LLM applications — replace trial-and-error prompt engineering with systematic evals, vulnerability scanning, and CI/CD integration.