This document covers Rich's live update system, which enables dynamic, auto-updating terminal displays. Live updates allow you to continuously refresh content in the terminal without scrolling, creating animated progress bars, status indicators, dashboards, and other interactive terminal interfaces.
The live update system consists of two main components:
Live class for creating custom auto-updating displays of any renderable contentStatus class and Spinner renderableFor information about progress bars, which are built on the live update system, see Progress Bars (page 4.3).
The live update system provides a mechanism to continuously update a region of the terminal without scrolling the screen. This is achieved through cursor positioning, ANSI control codes, and optional I/O redirection.
Live update diagram — key classes and their relationships:
Sources: rich/live.py1-298 rich/live_render.py1-117 docs/source/live.rst1-163
The Live class is the central component for creating auto-updating displays. It manages the lifecycle of a live display, handles refresh timing, redirects I/O, and coordinates with the Console.
| Component | Location | Purpose |
|---|---|---|
Live | rich/live.py41-294 | Main live display class with context manager support |
_RefreshThread | rich/live.py22-39 | Daemon thread that calls refresh() at regular intervals |
LiveRender | rich/live_render.py | Handles cursor positioning and vertical overflow |
RenderHook | rich/console.py | Protocol for intercepting and modifying renderables |
FileProxy | rich/file_proxy.py | Wraps stdout/stderr to redirect output above live display |
Live class method map:
Sources: rich/live.py41-298
The Live class supports automatic refreshing through a daemon thread that updates the display at a specified rate.
The _RefreshThread class rich/live.py22-39 is a simple daemon thread that:
refresh_per_second)_lock)refresh() to update the displayEvent objectAuto-refresh lifecycle sequence:
Key Parameters:
auto_refresh (bool): Enable/disable automatic refreshing rich/live.py84refresh_per_second (float): Refresh rate, must be > 0 rich/live.py89Thread Safety: All updates to _renderable and calls to refresh() are protected by an RLock rich/live.py82 to prevent race conditions between user code and the refresh thread.
See page 5.1 for the complete Live class reference.
Sources: rich/live.py22-39 rich/live.py84-89 rich/live.py141-143
Live displays work by:
Live implements the RenderHook protocol, allowing it to intercept renderables before they're printed to the console. The process_renderables() method rich/live.py278-297 modifies the list of renderables to include cursor control sequences.
Render pipeline comparison:
The LiveRender class rich/live_render.py13-117 handles cursor positioning:
Control.home() to reset to top-left| Method | Location | Purpose |
|---|---|---|
position_cursor() | rich/live_render.py51-70 | Move cursor to start of live display area |
restore_cursor() | rich/live_render.py72-84 | Clear live display area and restore cursor |
Control.home() | rich/control.py132-135 | Reset to top-left in alternate screen mode |
Sources: rich/live.py278-297 rich/live_render.py1-117
When content is too tall for the terminal, Live supports three overflow modes rich/live.py91:
| Mode | Behavior | Use Case |
|---|---|---|
"ellipsis" | Show "..." on last line when overflowing (default) | User should know content is truncated |
"crop" | Truncate at terminal height | Silent truncation acceptable |
"visible" | Allow content to exceed height (no clearing) | Final render or when scrolling is acceptable |
On exit, overflow is set to "visible" rich/live.py161 to allow the final frame to display completely.
Test coverage for each mode is in tests/test_live.py69-113
When transient=True rich/live.py86:
When transient=False (default):
Note: screen=True forces transient=True rich/live.py86
See tests/test_live.py54-66 for transient clearing behavior.
Setting screen=True rich/live.py74 enables the terminal's alternate screen buffer:
vim or less)Control.home() instead of relative positioningSources: rich/live.py57-96 rich/live.py126-128 rich/live.py161 rich/live.py172-173 tests/test_live.py161-169
To prevent print() or sys.stdout.write() from disrupting the live display, Live redirects stdout and stderr through a FileProxy.
I/O redirection flow:
Implementation Details:
_enable_redirect_io() rich/live.py195-203 replaces sys.stdout and sys.stderr with FileProxy instances_disable_redirect_io() rich/live.py205-212 restores original streamsredirect_stdout=True or redirect_stderr=True rich/live.py77-78FileProxy Behavior:
ConsoleSee tests/test_live.py130-143 for a test demonstrating print() statements appearing above the live display.
Sources: rich/live.py77-78 rich/live.py195-212 tests/test_live.py130-143
Rich supports nesting Live instances. When a Live is created within another Live context, the inner instance's content appears below the outer one rather than raising an error.
Nested Live stack rendering:
Key Implementation Points:
| Detail | Code Reference |
|---|---|
Stack management via Console._live_stack | rich/live.py221 |
Inner instances flagged with _nested=True | rich/live.py96 rich/live.py123 |
Only _live_stack[0] renders the full stack | rich/live.py221-228 |
Nested refresh() delegates to outer instance | rich/live.py248-251 |
| Nested stop prints content if not transient | rich/live.py152-155 |
Previous Behavior: Before Rich 14.1.0, nested Live instances raised a LiveError exception.
Sources: rich/live.py96 rich/live.py122-124 rich/live.py152-155 rich/live.py221-228 rich/live.py248-251
The Live class tightly integrates with the Console system:
| Method / Property | Purpose | Reference |
|---|---|---|
set_live(live) | Register Live instance with Console | rich/live.py122 |
clear_live() | Unregister Live instance | rich/live.py151 |
set_alt_screen(bool) | Enable/disable alternate screen buffer | rich/live.py127 rich/live.py177 |
show_cursor(bool) | Show/hide terminal cursor | rich/live.py128 rich/live.py175 |
push_render_hook(hook) | Register Live as a RenderHook | rich/live.py130 |
pop_render_hook() | Remove Live from hook chain | rich/live.py168 |
print(Control()) | Trigger a render cycle | rich/live.py271 |
is_jupyter | Detect Jupyter notebook environment | rich/live.py164 rich/live.py253 |
is_terminal | Detect terminal vs. file output | rich/live.py169 rich/live.py269 |
is_interactive | Detect interactive terminal | rich/live.py283 |
_live_stack | Ordered list of active Live instances | rich/live.py221 rich/live.py249 |
When console.is_jupyter is True rich/live.py253-268:
ipywidgets.Output widget for displayclear_output(wait=True) before each refreshipywidgets to be installed; warns otherwiseSources: rich/live.py111-178 rich/live.py253-276 rich/live.py278-297
Rich's documentation and examples directory contains several practical demonstrations:
| Example | File | Description |
|---|---|---|
| Basic table with auto-refresh | docs/source/live.rst16-37 | Live context manager with refresh_per_second |
| Replacing renderable on each update | docs/source/live.rst39-69 | Calling live.update() with a newly generated Table |
| Printing above the live display | docs/source/live.rst109-128 | Using live.console.print() or redirected print() |
| Animated table build | examples/table_movie.py1-197 | Staged Table construction with Live and screen=False |
top-style process monitor | examples/top_lite_simulator.py1-79 | Full-screen Live with screen=True and manual refresh |
| Exchange rate dashboard | rich/live.py300-405 | __main__ block in live.py demonstrating update() patterns |
Sources: docs/source/live.rst16-163 examples/table_movie.py1-197 examples/top_lite_simulator.py1-79
The Live Updates system provides:
Live class with configurable refresh ratesThe system is built on Rich's core rendering infrastructure, using the RenderHook protocol to intercept and modify output, and integrating tightly with the Console class for terminal control.
For detailed information on specific components, see:
Live class documentationSources: rich/live.py1-294 docs/source/live.rst1-163 CHANGELOG.md19
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.