mrkeyoor.com_
Wed 05 Aug 05:03 UTC
PyPICLI & Toolingupdated 05 Aug 2026

rich

Rich is the Python library for making terminal output look good. It gives you a drop-in print replacement with a bbcode-style markup for color and styling, plus ready-made renderables: tables, progress bars, spinners, trees, columns, markdown, syntax-highlighted code, and pretty tracebacks. It auto-detects terminal capability, word-wraps to the terminal width, works in Jupyter notebooks with no configuration, and pretty-prints any Python data structure. It is why so many modern Python CLIs (pip included) look the way they do.

Verdict

The best-in-class way to make Python terminal output presentable, and the default choice for application CLIs. Skip it inside libraries and machine-facing tools, and reach for Textual once you need interaction rather than display.

API stability4/5Console, Table, Progress, and the print API have been stable in shape for years, but major versions land often (v13 to v15 in about two years) with occasional rendering and signature changes.
Docs5/5readthedocs coverage of every renderable with examples, a runnable python -m rich demo, an examples directory in the repo, and the README alone is enough to get productive.
Maintenance4/5Still released and pushed to in 2026 (v15.0.0 current, push June 2026), but Textualize's center of gravity moved to Textual and Toad, and over 360 issues sit open.
Ecosystem5/5One of the most-downloaded packages on PyPI, a dependency of pip itself and of countless CLIs; the Console Protocol lets third-party objects render themselves.

Use it if

  • You build CLI tools and want tables, progress bars, and colored output without writing ANSI escape codes
  • You want readable debugging: rich tracebacks and inspect() beat staring at plain repr output
  • You need progress reporting for long jobs, including multiple concurrent bars and spinners
  • Your output runs in mixed environments (Linux, macOS, Windows Terminal, Jupyter) and you want capability detection handled for you
Skip it if

Setup reality

pip install rich and you are running in under a minute; python -m rich demos everything in your own terminal. There is no config. The gotchas are operational: Console(force_terminal=True) or the FORCE_COLOR conventions for CI where you DO want color, remembering markup like [bold] gets parsed in print calls (escape square brackets in user data), and major version bumps that arrive fairly frequently (v15 is current) occasionally adjust rendering details your snapshot tests may notice. Requires Python 3.9+ per current metadata.

Patterns

Drop-in print with color markupstyled-print

from rich import print

print("[bold magenta]Deploy[/bold magenta] finished :rocket:")
print({"status": "ok", "replicas": 3})

Square brackets in user-supplied strings are parsed as markup; print untrusted text via rich.markup.escape() or console.print(text, markup=False).

Use a Console for real applicationsconsole-object

from rich.console import Console

console = Console()
console.print("Hello", "World!", style="bold red")
console.print("Where there is a [bold cyan]Will[/bold cyan] there [u]is[/u] a way.")

Create one Console at module level and share it; it owns terminal-width detection and color capability for the process.

Render a data tablerender-table

from rich.console import Console
from rich.table import Table

table = Table(show_header=True, header_style="bold magenta")
table.add_column("Date", style="dim", width=12)
table.add_column("Title")
table.add_column("Box Office", justify="right")
table.add_row("Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$375,126,118")

Console().print(table)

Columns auto-shrink and wrap to fit the terminal; cells accept any Rich renderable, including nested tables.

Progress bar around any loopprogress-bar

from rich.progress import track

for step in track(range(100), description="Processing..."):
    do_step(step)

track() needs a sequence with a known length; for unknown totals use Progress with total=None or a status spinner.

Spinner for work with unknown durationstatus-spinner

from rich.console import Console

console = Console()
with console.status("[bold green]Working on tasks...") as status:
    for task in tasks:
        run(task)
        console.log(f"{task} complete")

console.log inside the status block prints above the live spinner without breaking it; run python -m rich.spinner to browse spinner styles.

Colorize the standard logging modulelogging-handler

import logging
from rich.logging import RichHandler

logging.basicConfig(
    level="INFO",
    format="%(message)s",
    datefmt="[%X]",
    handlers=[RichHandler()]
)
logging.getLogger("app").info("Server started")

Keep format minimal; RichHandler renders level, time, and caller location itself, so a full format string doubles the noise.

Install pretty tracebacks globallypretty-tracebacks

from rich.traceback import install

install(show_locals=True)

# any uncaught exception now renders with syntax highlighting
1 / 0

show_locals prints variable values at each frame, which is great for debugging and a secrets-leak risk in production logs.

Inspect any Python objectinspect-object

from rich import inspect

my_list = ["foo", "bar"]
inspect(my_list, methods=True)

inspect(obj, help=True) includes full docstrings; it is a REPL power tool, not something to leave in committed code.

Render Markdown in the terminalrender-markdown

from rich.console import Console
from rich.markdown import Markdown

with open("README.md") as readme:
    md = Markdown(readme.read())
Console().print(md)

Rendering is approximate by design; tables and headings translate well, raw HTML blocks inside the Markdown do not.

Print syntax-highlighted source codesyntax-highlight

from rich.console import Console
from rich.syntax import Syntax

code = open("app.py").read()
syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
Console().print(syntax)

Highlighting comes from pygments, so any pygments lexer name works as the language argument.

Pretty-print everything in the REPLpretty-repl

>>> from rich import pretty
>>> pretty.install()
>>> ["data", {"structures": True}]

After install(), every evaluated expression is pretty-printed and highlighted; add it to PYTHONSTARTUP to make it permanent.

Keep color in CI or piped outputforce-color-ci

from rich.console import Console

# CI pipes are not TTYs, so Rich disables color by default
console = Console(force_terminal=True, width=120)
console.print("[green]PASS[/green] 128 tests")

Fix the width too: without a TTY Rich cannot detect it and falls back to 80 columns, which mangles wide tables.

Alternatives

PackageRegistryPick it when
coloramaPyPIYou only need basic cross-platform colored text with near-zero footprint
tqdmPyPIYou only need a progress bar and want the lightest, most ubiquitous option
textualPyPIYou have outgrown printing and need a real interactive terminal UI with widgets and events