Not just a traceback formatter — but a universal exception handler. A single @decorator that transforms every exception into a structured, multi-format report
Project description
Catch Them All
Not just a traceback formatter — but a universal exception handler.
A Single @decorator that transforms every exception into a structured, multi‑format report
Table of Contents
Features
╭── Features Overview
│
├── Catching & Handling Exceptions
│ ├── @pokeball decorator : Wrap functions to catch exceptions automatically.
│ ├── PokedexReport : Structured report object with multiple formats (.show(), .str_format, .to_log(), etc.).
│ ├── on_catch() hook : Run custom logic (logging, retries, alerts) on catch.
│ ├── log flag : Optional auto-logging to file.
│ ╰── Scales anywhere : OS- and framework-agnostic – web apps, CLI tools, scripts, pipelines.
│
╰── Beautiful Traceback Formatting (shared by @pokeball and uncaught exceptions)
├── Intelligent summaries : Auto-extracted from exception docstrings for concise context.
├── Structured panels : Clear layout with visual boundaries.
├── Smart color grouping : Highlighted exceptions, code, unified labels, and matching colors for function ↔ line number
╰── Style class : Full Rich-powered theme customization.
Installation
Install via pip:
pip install catch-them-all
On Import
When you import catch_them_all, these behaviours trigger automatically:
-
Exception scanning
- All imports (and their dependencies) are scanned for exception classes.
- A summary registry is built, keyed as
module__name__.exception__name__, storing names and docstring summaries for use in reports.
-
Exception hook
- A custom
sys.excepthookreplaces Python’s default traceback, giving clear, structured output right away. - To keep the default traceback, disable the hook:
from catch_them_all import disable_excepthook disable_excepthook()
- A custom
Usage
Description:
Wrap functions with @pokeball to automatically catch exceptions, format them with your chosen theme, and optionally log the report.
Example 1:
- Instead of manually adding
try/exceptblocks:
try:
something()
except Exception as e:
logger.exception(e)
- You can simply do this:
from catch_them_all import pokeball
@pokeball(log="errors.log")
def something():
raise RuntimeError
- The
logflag is optional and writes reports to the specified file.
Log file :
- Note : A decorator always adds a frame in the traceback, that why you see
wrapper()in the Stack, it is the natural behaviour of Python Decorators
Example 2:
- Instead of importing custom exceptions and scattering
try/exceptblocks:
from requests.exceptions import RequestException, HTTPError, ConnectionError, Timeout
from sqlalchemy.exc import SQLAlchemyError, IntegrityError, OperationalError
from sklearn.exceptions import NotFittedError, ConvergenceWarning
try:
func_might_raise()
except ConnectionError:
handling_logic()
- You can decorate the function with
@pokeballand passhandling_logicfuncto it:
from catch_them_all import pokeball
@pokeball(on_catch=handling_logic)
def func_might_raise():
... # code
+ This eliminates the need to import and manage multiple Custom exception classes manually
-
Keeping error handling Clean, Centralized, and Easier to Maintain.
-
Exception➜ Raises ➜Pokeball➜ Catches ➜On_Catch➜ Triggers ➜User➜ Decides.
Description:
excepthook is a custom traceback formatter from catch_them_all.
It is fully customizable, leveraging Rich’s styling and color features to produce clearer, structured tracebacks.
- Automatic setup → styled tracebacks are enabled out of the box.
- Global hook → replaces Python’s default
sys.excepthook. - Fully Customisable → via
Styleclass.
More info in Exception Hook section.
Example:
import catch_them_all
raise RuntimeError("Uncaught exception demo")
- Output: Fully Styled Traceback:
- instead of Python's native traceback
Pokeball Decorator
A simple example using requests to demonstrate how exceptions are caught, context is injected, and reports are handled
- Decorator usage → wrapping the entry function with
@pokeball. - Context injection → enriching the report with runtime variables.
- Passing
on_catch→ supplying a custom handler for caught exceptions. - Programmatic intervention → retrying or logging based on exception type.
Example:
import requests
from catch_them_all import pokeball, rescan_imports
# Import Catch Them All last (after libraries you want scanned)
# or call rescan_imports() explicitly if needed
def re_run():
print("Retrying request...")
# user code ...
# Context variables that would normally flow through your integration layer
web_address = "http://nonexistent.example.com"
ip = "192.168.0.42" # imagine from get_ip()
user_agent = "Mozilla/5.0" # imagine from get_user_agent()
def on_catch(report, web_address, ip, user_agent):
# Inject context into the report
report.inject_context({
"web_address": web_address,
"ip": ip,
"user_agent": user_agent,
})
# Show Rich Format traceback
report.show()
# Conditional handling
if report.name == "ConnectionError" and report.module.startswith("requests"):
re_run() # handle programmatically
else:
report.to_log("errors.log")
@pokeball(on_catch=on_catch, on_catch_args=(web_address, ip, user_agent))
def main():
# This will raise a requests.exceptions.ConnectionError
requests.get(web_address)
if __name__ == "__main__":
obj = main()
# If no exception was raised, obj is the normal return value.
# If exception was caught, obj is a PokedexReport instance.
Note: These Exceptions are excluded:
KeyboardInterruptSystemExitGeneratorExitandMemoryErroras these are Critical System Exceptions that must propagate.SyntaxError,TabError, andIndentationError, which occur at parse time before runtime.
Note:
- The ~12‑second delay observed in the
@pokeballexample is due torequeststrying to resolve a non‑existent address. It’s not related tocatch_them_allitself.
IDE Output when an Exception is raised:
- Dual Exception Panel for Convenience.
- User Injected Context Panel
- Indented Stack Frames
Instead of Python's native traceback:
Note: Use .str_format for plain, CLI‑friendly output without Rich color codes. it's especially useful when Rich colors aren't supported.
# Show Str Format traceback
print(report.str_format)
CLI output :
PokedexReport Object
The PokedexReport object is created whenever an exception is caught.
It unifies error details, context, and multiple output formats into a single structure,
making it easy to inspect, log, or display exceptions programmatically.
╭── PokedexReport Instance:
│
├── Attributes:
│ ├── name : Exception class name (e.g., "ConnectionError"). ─────────────────────╮
│ ├── module : Module where the exception is defined (e.g., "requests.exceptions") │
│ ├── msg : Exception message / string representation. │
│ ├── summary : One-line human-readable summary from the registry. │
│ ├── frames : List of distilled stack frame dicts.(e.g., line_no, file...). ├──{Error Info}
│ ├── timestamp : ISO timestamp when the exception occurred. │
│ ├── caused_by : Chain of causing exceptions (if any). │
│ ├── user_context : User-provided context (e.g., user_id, request data). ────────────────╯
│ │
│ ├── formatted_object : Internal Formatter instance for rendering. ──────────────────╮
│ │ ├── header : Exception box (summary + metadata). ├──{Formatter components}
│ │ ├── frames : Stack trace frames. │
│ │ └── context_panel : Injected user context. ────────────────────────────────╯
│ │ (In case a user requires specific component)
│ │
│ ├── json_format : Cached dict representation. ───────────────────────────────────╮
│ ├── log_format : Plain-text version without footer, suitable for logs. ├──{Output formats}
│ ├── rich_format : Rich object for styled terminal display. │
│ ╰── str_format : Plain-text CLI-friendly version. ──────────────────────────────╯
│
├── Methods:
│ ├── .to_dict() : Return attributes as a Python dict. ──────────────────────╮
│ ├── .to_log(path) : Append plain-text report to a log file. │
│ ├── .to_json(path=None) : Serialize to JSON string, or write to file if path given. ├──{Report methods}
│ ├── .show() : Render rich report to console. │
│ ╰── .inject_context(ctx): Add user-defined context dictionary. ─────────────────────╯
│
╰──────────────────────────────────────────────────────────────────────────────────────────╯
Exception Hook:
By default, catch_them_all installs its custom sys.excepthook, so uncaught exceptions are automatically formatted with the same styled traceback used by @pokeball.
- Automatic setup → styled tracebacks are enabled out of the box.
- Global hook → replaces Python’s default
sys.excepthook. - Styled output → applies your configured
Styleto uncaught exceptions. - Persistent theme → if you’ve set a global style or exported one.
- disable_excepthook() → restore Python’s default hook.
Disabling Excepthook :
from catch_them_all import disable_excepthook, Style, set_global_style
# excepthook is enabled by default, but you can disable it:
disable_excepthook() # back to Python's default
Changing Exception Hook Theme:
from catch_them_all import Style, set_global_style
# customize style
style = Style(header_border="dark_cyan",
header_message="dark_slate_gray3",
stack_border="deep_sky_blue3",
)
# trigger an uncaught exception
raise RuntimeError("Uncaught exception demo")
Note: You can use Style.colors() and Style.styles() to print and return a list of Rich styles and colors to use, or visit Rich docs.
Output:
Style Customization
Customizing traceback output with the Style class:
- Full customization → adjust the formatted traceback exactly as you like.
- Rich compatibility → pass any values supported by Rich
TextStyle. - Granular control → override a single attribute or multiple at once.
- Shared usage → applies to both
excepthookand@pokeballformatted tracebacks.
╭── Style Instance
│
├── Attributes:
│ ├── labels : Style for metadata labels (e.g. "message:", "code:", "info:"). ├── Generic
│ ├── muted : Style for secondary or de‑emphasized text.
│ │
│ ├── header_border : Border style for header panel. (e.g., "medium_turquoise") ─────────────────────╮
│ ├── header_exception : Style for exception type in header. (e.g., "bold yellow") │
│ ├── header_timestamp : Style for timestamp in header. (e.g., "italic #af00ff") ├──{Exception Header Propoerties}
│ ├── header_summary : Style for summary line. (e.g., "italic rgb(175,0,255)") │
│ ├── header_message : Style for message label. │
│ ├── header_cause : Style for cause label. ────────────────────────────────────────────────────────╯
│ │
│ ├── stack_indent : Indentation spaces per frame level (0–6).─────────────────────╮
│ ├── stack_border : Border style for frame panels. ├──{Traceceback Stack Properties}
│ ├── stack_func_and_line_no : Style for function name + line number. │
│ ├── stack_file_path : Style for file path. ─────────────────────────────────────────╯
│ │
│ ├── context_border : Border style for user context panel.────────────────────────────────────────╮
│ ├── context_keys : Style for user context Dict keys. ├──{User Injected Context Properties}
│ ╰── context_values : Style for user context Dict values.─────────────────────────────────────────╯
│
├── Methods:
│ ├── styles() : Return list of available Rich text styles.
│ ├── colors() : Return list of available Rich colors.
│ ├── export_style() : Export current Style to JSON file.
│ ├── load_style() : Load Style from JSON file or defaults.
│ ╰── to_dict() : Serialize Style instance to dictionary.
│
╰─────────────────────────────────────────────────────────────────╯
Changing Theme:
from catch_them_all import Style, set_global_style
# build style
custom_style = Style(
header_border="red",
header_exception="red on grey7",
header_timestamp="light_cyan3",
stack_border="navajo_white3",
stack_func_and_line_no="grey63",
stack_code="medium_purple2 on grey19"
)
# set style globally
set_global_style(custom_style)
# or save it — next time you use catch_them_all, it will load automatically
custom_style.export_style() # if no path is provided, saves to ~/.catch_them_all/style.json
def demo_function():
try:
# Inner exception
raise TypeError("TypeError message demo.")
except TypeError as inner:
try:
# Another nested exception
raise ValueError("ValueError message demo.") from inner
except ValueError as outer:
# Final wrapping to show cause chain
raise RuntimeError("RuntimeError wrapping ValueError.") from outer
# Call the function to trigger the styled traceback
demo_function()
Output:
Restoring Default Theme:
from catch_them_all import restore_default_style
# You simply run
restore_default_style()
Note : restore_default_style() exports the default style, which will be loaded automatically on the next run.
Output:
Public API
pokeball→ decorator for catching and formatting exceptions.rescan_imports()→ rescans modules that were imported aftercatch_them_all.Style→ class for customizing traceback appearance.set_global_style()→ apply a custom style globally.restore_default_style()→ restore the default theme forexcepthookand@pokeball.disable_excepthook()→ restore Python’s default behavior.install_excepthook()→ only needed to re‑enable the custom formatter if it was disabled, without re‑importing the module.
Contributing
This project is maintained as time and resources permit. The community is encouraged to contribute, fork, and modify the code freely. Contributions are always welcome and appreciated.
You are encouraged to:
- Submit pull requests for bug fixes or feature enhancements.
- Fork the repository and adapt it to suit your needs.
- There are no strict guidelines or requirements for contributing.
- This project is a collaborative effort for the benefit of the community.
Contributions are appreciated, though reviews may be slow. With limited maintainer availability, pull requests might remain open for an extended period before approval.
Publishing to PyPI
This project is published on PyPI as catch_them_all.
If you contribute a significant feature and would like to publish it, please request to be added as a maintainer on PyPI by opening an issue.
Alternatively, feel free to fork this project and publish your version independently.
Author
Created by Anasse Gassab.
Licenses
catch_them_allis licensed under the MIT License – see the LICENSE file for details.Richis licensed under the MIT license. See Rich License for details.
Acknowledgements
-
This project uses the Rich library for advanced text formatting and styling.
-
Thanks to the Python community for the awesome libraries like
rich. -
Created to make debugging less painful and more fun — saving developers time on boilerplate and ugly tracebacks, with a Pokémon twist, for the whole community to enjoy.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file catch_them_all-1.0.1.tar.gz.
File metadata
- Download URL: catch_them_all-1.0.1.tar.gz
- Upload date:
- Size: 667.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.7.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c96a7509dc299f73a31d7e9c47df9f35208d69c872693312f474b6f4b4a41527
|
|
| MD5 |
63a1157f3d05082817aca1189cbde448
|
|
| BLAKE2b-256 |
339df95b09a4e3001e7ec9eb091a0c389fcac5a3c755335e562294cc7c9d7f3d
|
File details
Details for the file catch_them_all-1.0.1-py3-none-any.whl.
File metadata
- Download URL: catch_them_all-1.0.1-py3-none-any.whl
- Upload date:
- Size: 32.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.7.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b62011cf2379ee58544241b1dc503d63cc942165e873a18d713bc19bcf008e9
|
|
| MD5 |
102bffcd7efae191c385d1b79004e45a
|
|
| BLAKE2b-256 |
3cac6326f5b591a6af5fa65e240fdea284bb4af2b82e28956ea42ba01337709a
|