This page documents the Status and Spinner classes in Rich, which together produce animated spinner indicators in the terminal. Status is a high-level context manager that displays a spinner alongside a status message. Spinner is the lower-level renderable that implements the frame-based animation.
For the underlying auto-refresh mechanism that drives these components, see the Live Display page. For general progress reporting with bars and tasks, see Progress Bars.
Status and Spinner sit in the Live display subsystem. Status wraps a Live instance and a Spinner instance into a single, easy-to-use interface for "working on something…" type indicators.
Component relationships:
Sources: rich/status.py1-107 rich/spinner.py1-115 rich/live.py1-40
The SPINNERS dictionary in rich/_spinners.py is the data source for all available spinner animations. Each entry maps a string name to a dictionary with two keys:
| Key | Type | Description |
|---|---|---|
frames | List[str] | Ordered list of Unicode strings, one per animation frame |
interval | float | Milliseconds between frames at speed=1.0 |
Spinner.__init__ looks up the name in this registry and raises KeyError if the name is not found rich/spinner.py36-37
To view all available spinners interactively:
python -m rich.spinner
File: rich/spinner.py
Class: Spinner
Spinner is a renderable that animates by selecting a frame from its frames list based on elapsed time.
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | required | Key into SPINNERS registry |
text | RenderableType | "" | Content displayed to the right of the spinner frame |
style | StyleType | None | Style applied to the spinner frame characters |
speed | float | 1.0 | Multiplier on animation speed |
The core of animation is in Spinner.render(time) rich/spinner.py61-93:
frame_no = ((time - start_time) * speed) / (interval / 1000.0) + frame_no_offset
frame = frames[int(frame_no) % len(frames)]
time is a float in seconds (sourced from Console.get_time() via __rich_console__).start_time is set on the first call to render().interval is in milliseconds, so dividing by 1000.0 converts to seconds per frame.frame_no_offset enables smooth speed transitions without a jump in the displayed frame.Frame selection diagram:
Sources: rich/spinner.py70-78
How render() combines the spinner frame with text rich/spinner.py86-93:
text value | Output renderable |
|---|---|
| Empty / falsy | Frame Text only |
str or Text | Text.assemble(frame, " ", self.text) |
| Any other renderable | Table.grid(padding=1) with frame in column 0, text in column 1 |
Spinner.update() rich/spinner.py95-114 accepts text, style, and speed. Speed changes are applied indirectly: the new speed is stored in _update_speed and applied on the next render() call, which also recalculates frame_no_offset so the animation does not jump.
| Method | Behavior |
|---|---|
__rich_console__ | Calls self.render(console.get_time()) and yields the result |
__rich_measure__ | Calls self.render(0) to measure width at time zero |
File: rich/status.py
Class: Status
Status is a thin wrapper around Live and Spinner that manages a transient, auto-refreshing spinner display.
| Parameter | Type | Default | Description |
|---|---|---|---|
status | RenderableType | required | The status message to display |
console | Console | None | Console instance; uses global console if None |
spinner | str | "dots" | Name of the spinner animation |
spinner_style | StyleType | "status.spinner" | Style applied to spinner frames |
speed | float | 1.0 | Speed multiplier for spinner |
refresh_per_second | float | 12.5 | Live display refresh rate |
Status.__init__ always passes transient=True to Live, so the spinner disappears when the context exits rich/status.py37-42
Sources: rich/status.py11-106
Sources: rich/status.py53-106
Status.update() handles two cases rich/status.py53-83:
Spinner object is created with the current status, spinner_style, and speed, then passed to Live.update() with refresh=True.Spinner.update() is called with the new text, style, and speed values directly. The live display picks up the change on its next auto-refresh cycle.update() parameter | Effect |
|---|---|
status | Updates status message text on the spinner |
spinner | Replaces _spinner with a new Spinner instance |
spinner_style | Changes frame styling |
speed | Changes animation speed (deferred via _update_speed) |
The console property on Status delegates directly to self._live.console rich/status.py48-51 This is the console that should be used for any print or log calls while the status indicator is running, so that output appears above the spinner.
The Console class exposes a status() convenience method (documented in Console) that constructs and returns a Status object configured with that console. Using it is equivalent to:
Status sets transient=True when constructing its internal Live, which means:
stop() is called.with block.The refresh_per_second=12.5 default (higher than Live's default of 4) is chosen to make spinner animations appear smooth.
For cases where persistent output is needed, or for more complex multi-component displays, use Live directly rather than Status. See Live Display.
| Symbol | File | Role |
|---|---|---|
SPINNERS | rich/_spinners.py | Registry of all named spinner animations |
Spinner | rich/spinner.py | Renderable; selects frame by time |
Spinner.render(time) | rich/spinner.py | Core frame selection calculation |
Spinner.update() | rich/spinner.py | Mutates text/style/speed of a running spinner |
Status | rich/status.py | High-level context manager wrapping Live + Spinner |
Status.update() | rich/status.py | Updates status message, spinner name, style, or speed |
Status._live | rich/status.py | Internal Live(transient=True) instance |
Status._spinner | rich/status.py | Internal Spinner instance used as the live renderable |
Live | rich/live.py | Auto-refresh engine driving the terminal animation |
Sources: rich/spinner.py1-115 rich/status.py1-107 rich/live.py1-97
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.