This page documents rich.traceback: the Traceback renderable class, the install() exception hook, and the internal data structures (Trace, Stack, Frame) used to capture and display Python exceptions with syntax highlighting and local variable display.
For integration with Python's logging module (which uses Traceback internally when rich_tracebacks=True), see Logging Integration. For the Syntax renderable that renders highlighted code inside tracebacks, see Syntax Highlighting.
rich/traceback.py provides a drop-in replacement for Python's default traceback printer. It walks the exception chain, extracts per-frame metadata into a structured data model, and renders the result as a Rich Panel with syntax-highlighted source code, optional local variable display, and fine-grained error position highlighting on Python 3.11+.
Data flow diagram:
Sources: rich/traceback.py84-218 rich/traceback.py262-350
The extraction process populates three nested dataclasses before any rendering occurs.
Structure diagram:
Sources: rich/traceback.py222-255
| Field | Type | Notes |
|---|---|---|
Frame.filename | str | Absolute path; resolved from _IMPORT_CWD if relative |
Frame.lineno | int | Line number at point of call |
Frame.locals | Optional[Dict[str, pretty.Node]] | None unless show_locals=True |
Frame.last_instruction | Optional[Tuple[Tuple[int,int], Tuple[int,int]]] | Python 3.11+ only; ((start_line, start_col), (end_line, end_col)) |
Stack.is_cause | bool | True for raise X from Y; False for implicit chaining |
Stack.is_group | bool | True when exception is ExceptionGroup (3.11+) |
Stack.exceptions | List[Trace] | Populated for ExceptionGroup sub-exceptions |
Traceback ClassTraceback in rich/traceback.py262-350 is a Console renderable (implements __rich_console__). It holds a Trace object and all display configuration.
Three construction paths exist:
| Method | Use case |
|---|---|
Traceback(trace=None) | Must be called inside an except block; reads sys.exc_info() |
Traceback.from_exception(exc_type, exc_value, traceback, ...) | Use when you have an explicit exception tuple |
Traceback.extract(exc_type, exc_value, traceback, ...) | Produces only the Trace data without rendering config |
from_exception() is the most commonly used path — it calls extract() then wraps the result in a Traceback instance rich/traceback.py352-430
| Parameter | Default | Description |
|---|---|---|
width | 100 | Overall panel width in characters |
code_width | 88 | Width of the code block inside the panel |
extra_lines | 3 | Lines of context shown above and below the error line |
theme | None → "ansi_dark" | Pygments theme name or SyntaxTheme instance |
word_wrap | False | Enable word wrapping in code display |
show_locals | False | Display local variable values per frame |
locals_max_length | 10 | Container truncation threshold |
locals_max_string | 80 | String truncation threshold |
locals_max_depth | None | Nested structure depth cap |
locals_hide_dunder | True | Hide __dunder__ locals |
locals_hide_sunder | False | Hide _sunder locals (auto-set to True in Jupyter) |
indent_guides | True | Show indent guides in code and locals |
suppress | () | Modules or path strings to suppress (see below) |
max_frames | 100 | Maximum frames to show; 0 = unlimited |
Sources: rich/traceback.py295-350
install() Functioninstall() in rich/traceback.py84-218 replaces sys.excepthook with a closure that calls Traceback.from_exception() and prints to stderr.
It accepts all the same configuration parameters as Traceback.__init__(). It returns the previous sys.excepthook so it can be restored.
IPython support: When running inside IPython, install() detects this via get_ipython() and patches ip._showtraceback and ip.showtraceback instead of sys.excepthook, preserving IPython features like the debugger rich/traceback.py166-218
Sources: rich/traceback.py84-218
Traceback.extract()extract() in rich/traceback.py432-624 walks the exception chain and populates the Trace → Stack → Frame hierarchy.
Extraction flow diagram:
Sources: rich/traceback.py432-624
Two special local variable names control frame visibility during extraction:
| Local variable | Effect |
|---|---|
_rich_traceback_omit = True | The frame is skipped entirely and not added to Stack.frames |
_rich_traceback_guard = True | All frames accumulated so far in this Stack are cleared; useful in framework dispatch code to hide internal frames |
Sources: rich/traceback.py572-597
Traceback.__rich_console__() rich/traceback.py626-726 is called by the Console rendering pipeline. It builds a custom Theme derived from the active syntax theme and calls _render_stack() for each Stack in self.trace.stacks (in reverse order, root cause first).
Rendering component diagram:
_render_stack()_render_stack() rich/traceback.py767-895 iterates Stack.frames and for each frame:
PathHighlighter.linecache.getlines()._guess_lexer() rich/traceback.py751-765 which checks LEXERS for .py, .pxd, .pyx, .pxi then falls back to Pygments' guess_lexer_for_filename.Syntax object with line_range=(lineno - extra_lines, lineno + extra_lines) and highlight_lines={lineno}.syntax.stylize_range("traceback.error_range", ...) using Frame.last_instruction positions.show_locals=True, renders the Frame.locals via render_scope() in a side-by-side Columns layout.Frame suppression via suppress: If the frame's filename starts with any path in self.suppress, the source code block is omitted; only the file/line/function header is shown.
Frame truncation via max_frames: When len(stack.frames) > max_frames, the middle portion is replaced with a ... N frames hidden ... message, keeping the first max_frames // 2 and last max_frames // 2 frames rich/traceback.py784-803
Sources: rich/traceback.py767-895
On Python 3.11+, co_positions() on a code object returns per-instruction source position tuples. extract() uses this to populate Frame.last_instruction rich/traceback.py543-567:
instruction_index = frame_summary.f_lasti // 2
instruction_position = next(islice(frame_summary.f_code.co_positions(), instruction_index, instruction_index + 1))
# yields (start_line, end_line, start_column, end_column)
This allows the renderer to underline the exact sub-expression that caused the error (e.g., highlighting 1 / 0 precisely at the / operator) using the traceback.error_range style. The helper _iter_syntax_lines() rich/traceback.py56-81 breaks multi-line ranges into per-line (line, col1, col2) tuples for Syntax.stylize_range().
On Python < 3.11, Frame.last_instruction is None and no sub-expression highlighting is performed.
Sources: rich/traceback.py56-81 rich/traceback.py543-567 rich/traceback.py862-884
The suppress parameter accepts module objects or path strings. During __init__, each entry is converted to an absolute directory path rich/traceback.py339-349:
ModuleType is passed, os.path.dirname(module.__file__) is used.str is passed, it is used directly after os.path.normpath(os.path.abspath(...)).At render time, a frame is considered suppressed if frame.filename.startswith(path) for any path in self.suppress. Suppressed frames display only the header line; their source code block is omitted.
Sources: rich/traceback.py339-350 rich/traceback.py808-832
ExceptionGroupextract() follows Python's exception chain automatically:
| Chain type | Trigger | Stack.is_cause |
|---|---|---|
Explicit (raise B from A) | exc.__cause__ is not None | True |
Implicit (raise B inside except A) | exc.__context__ with __suppress_context__=False | False |
The stacks are collected in chain order (outermost last), then reversed during rendering so the root cause is shown first.
For ExceptionGroup (Python 3.11+), the Stack.is_group flag is set and each sub-exception is recursively extracted into Stack.exceptions (a list of Trace objects). These are rendered as nested Panel instances labeled "Sub-exception #N" rich/traceback.py700-713
Sources: rich/traceback.py491-620
Console.print_exception()The most common usage path for tracebacks goes through Console.print_exception(), which internally calls Traceback.from_exception() with all its keyword arguments forwarded. This is the equivalent of calling:
This method is not defined in rich/traceback.py but is part of the Console class described in Console.
When show_locals=True, each Frame.locals dictionary is populated during extraction by calling pretty.traverse(value, ...) for every local variable rich/traceback.py579-592:
inspect.isfunction, inspect.isclass).locals_hide_dunder / locals_hide_sunder filter __dunder__ and _sunder names.Dict[str, pretty.Node] — pre-traversed Node trees from the pretty module — rendered via render_scope() from rich/scope.py.At render time, locals appear in a Columns([syntax, render_scope(...)]) layout next to the code block when frame.locals is non-empty.
Sources: rich/traceback.py524-592 rich/traceback.py771-782 rich/traceback.py885-895
The traceback renderer applies styles from the active theme. These names can be overridden via a custom Theme (see Themes and Customization):
| Style name | Applied to |
|---|---|
traceback.title | Panel title text |
traceback.border | Panel border |
traceback.border.syntax_error | Syntax error panel border |
traceback.exc_type | Exception type name |
traceback.error | Error message and "frames hidden" text |
traceback.error_range | Sub-expression highlight (Python 3.11+) |
traceback.note | [NOTE] prefix on exception notes |
traceback.group.border | ExceptionGroup sub-exception panel border |
Sources: rich/traceback.py626-726
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.