C.W.K.
Stream
Lesson 04 of 04 · published

Rich — Pretty Terminal Output

~15 min · rich, terminal, color, progress

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

rich — making terminals look like 2026, not 1995

rich is a Python library for rich text and beautiful formatting in the terminal. Color, tables, progress bars, syntax-highlighted code, formatted tracebacks. Drops into your scripts with one import; auto-detects whether the output is a TTY (and gracefully degrades when it isn't).

rich.print — the upgrade

One-liner: from rich import print shadows the builtin. Now print({"a": 1, "b": [1, 2, 3]}) auto-pretty-prints with colors. print("[bold red]hello[/bold red]") uses BBCode-like markup. Quick wins for any script that produces output.

Tables and progress bars

rich.table.Table for actual tables with borders, alignment, styles. rich.progress.track wraps an iterable to show a progress bar. rich.progress.Progress for richer multi-task progress. The defaults look professional out of the box.

rich tracebacks

from rich.traceback import install; install() — installs rich as the default traceback handler. Crashes now produce colored, syntax-highlighted tracebacks with local variables shown in context. Massively faster to read than plain Python tracebacks. cwkPippa uses this.

Pythonic Way: For any script that has a human in the loop reading the output, rich is a free upgrade. The install() + from rich import print two-liner makes everything more readable. typer integrates rich automatically; argparse + rich also works without ceremony.

Code

rich.print — drop-in upgrade·python
# pip install rich
from rich import print

# Auto-pretty for complex types
print({"name": "alice", "items": [1, 2, 3], "active": True})
# {'name': 'alice', 'items': [1, 2, 3], 'active': True}    — colored

# Markup-like styling
print("[bold red]error:[/bold red] something failed")
print("[green]ok[/green] all good")
print("[blue underline]https://example.com[/blue underline]")
Tables — formatted, aligned·python
from rich.console import Console
from rich.table import Table

console = Console()

table = Table(title="Stocks", show_lines=True)
table.add_column("Ticker", style="cyan", no_wrap=True)
table.add_column("Price", justify="right", style="green")
table.add_column("Volume", justify="right")

table.add_row("AAPL", "$180.25", "45M")
table.add_row("NVDA", "$950.00", "32M")
table.add_row("MSFT", "$420.50", "28M")

console.print(table)
Progress bars·python
from rich.progress import track
import time

# Wrap any iterable
for item in track([1, 2, 3, 4, 5], description="Processing..."):
    time.sleep(0.5)
# Animated progress bar with ETA

# More control
from rich.progress import Progress

with Progress() as progress:
    task = progress.add_task("[red]Downloading...", total=100)
    for _ in range(100):
        time.sleep(0.01)
        progress.update(task, advance=1)
rich tracebacks — install once·python
from rich.traceback import install
install(show_locals=True)

# Now any uncaught exception prints with:
# - syntax-highlighted source code
# - the offending line highlighted
# - local variables shown in context

def divide(a, b):
    return a / b

# divide(10, 0)
# Traceback (most recent call last):
#   File "...", line 8, in <module>
#     divide(10, 0)
#   File "...", line 6, in divide
#     return a / b
# ZeroDivisionError: division by zero
#
# but with COLOR and the local variables a=10, b=0 displayed

External links

Exercise

Write a small script that: (a) installs rich tracebacks at the top, (b) uses rich.print to print a colored welcome message and a dict, (c) builds a Table with 3 columns of stock data and 5 rows, (d) uses rich.progress.track to wrap a range(20) iteration with a sleep. Run it. Then deliberately raise a ZeroDivisionError and observe the rich traceback.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.