Beautiful Terminal Output with Rich
Rich is a Python library that lets you build rich terminal output with colors, styles, tables, progress bars, syntax highlighting, and markdown rendering. It works on Linux, macOS, and Windows, and automatically handles terminal capabilities.
Why Rich?
Standard print statements are plain and utilitarian. Rich makes your CLI applications look professional with minimal effort:
from rich.console import Console
console = Console()
console.print("Hello, [bold red]World![/bold red]")
That one line produces bold red text in any terminal that supports colors.
Installation
Install Rich with pip:
pip install rich
That’s it. No configuration needed.
Getting Started
The Console object is your main entry point:
from rich.console import Console
console = Console()
# Basic colored text
console.print("[bold blue]This is bold blue[/bold blue]")
console.print("[italic green]This is italic green[/italic green]")
console.print("[underline yellow]This is underlined yellow[/underline yellow]")
# Combine styles
console.print("[bold cyan]Bold cyan[/bold cyan] with [inverse]inverse[/inverse]")
Rich uses a simple markup syntax similar to BBCode. Wrap text in square brackets with style names.
Available Colors
Rich supports 8-bit, true color (24-bit), and terminal default colors:
# Standard colors
console.print("[red]Red[/red]")
console.print("[blue]Blue[/blue]")
console.print("[green]Green[/green]")
# Bright variants
console.print("[bright_red]Bright Red[/bright_red]")
console.print("[bright_cyan]Bright Cyan[/bright_cyan]")
# 256-color (0-255)
console.print("[color(202)]Copper orange[/color(202)]")
# True color (RGB)
console.print("[rgb(255,128,0)]Orange[/rgb(255,128,0)]")
Text Styles
Beyond colors, Rich provides numerous text styles:
console.print("[bold]Bold text[/bold]")
console.print("[dim]Dim text[/dim]")
console.print("[italic]Italic text[/italic]")
console.print("[underline]Underlined text[/underline]")
console.print("[strike]Strikethrough[/strike]")
console.print("[blink]Blinking text[/blink]")
console.print("[reverse]Reversed colors[/reverse]")
console.print("[conceal]Hidden text[/conceal]")
Not all terminals support all styles—Rich gracefully degrades when they don’t.
Tables
Rich can render beautiful ASCII tables:
from rich.console import Console
from rich.table import Table
console = Console()
table = Table(title="Programming Languages")
table.add_column("Language", style="cyan", no_wrap=True)
table.add_column("Creator", style="magenta")
table.add_column("Year", justify="right", style="green")
table.add_row("Python", "Guido van Rossum", "1991")
table.add_row("JavaScript", "Brendan Eich", "1995")
table.add_row("Rust", "Graydon Hoare", "2010")
table.add_row("Go", "Robert Griesemer", "2009")
console.print(table)
The output looks like a proper terminal table with borders and aligned columns.
Table Styles
Customize table appearance:
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Name", style="cyan")
table.add_column("Status", justify="center")
# Different row styles
table.add_row("Task 1", "[green]✓ Complete[/green]")
table.add_row("Task 2", "[yellow]⟳ In Progress[/yellow]")
table.add_row("Task 3", "[red]✗ Failed[/red]")
console.print(table)
You can also use Table.row_styles for alternating row colors.
Progress Bars
Rich includes built-in progress tracking:
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn
with Progress(
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
) as progress:
task = progress.add_task("[cyan]Processing...", total=100)
for i in range(100):
progress.update(task, advance=1)
For multiple concurrent tasks:
from rich.progress import Progress
with Progress() as progress:
task1 = progress.add_task("[red]Downloading...", total=100)
task2 = progress.add_task("[blue]Installing...", total=100)
for i in range(100):
progress.update(task1, advance=1)
for i in range(100):
progress.update(task2, advance=0.5)
progress.update(task2, advance=0.5)
Track Function
For simple progress tracking, use track:
from rich.progress import track
for i in track(range(100), description="Processing..."):
do_work()
Logging
Rich can replace or augment Python’s logging:
from rich.logging import RichHandler
import logging
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
handlers=[RichHandler(rich_tracebacks=True)]
)
logger = logging.getLogger(__name__)
logger.info("This is an info message")
logger.warning("This is a warning")
logger.error("This is an error")
The RichHandler adds color-coded log levels and optionally includes tracebacks.
Syntax Highlighting
Rich includes a syntax highlighter using the same themes as VS Code:
from rich.syntax import Syntax
from rich.console import Console
code = """
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
for i in range(10):
print(f"F({i}) = {fibonacci(i)}")
"""
syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
console.print(syntax)
Available themes include monokai, github-dark, dracula, and many more.
Markdown
Render Markdown directly in the terminal:
from rich.markdown import Markdown
from rich.console import Console
console = Console()
markdown = """
# Heading 1
This is **bold** and *italic* text.
## Code Blocks
````python
print("Hello")
This is a quote
- Item 1
- Item 2 """
console.print(Markdown(markdown))
## Panels
Group content in boxes:
```python
from rich.panel import Panel
from rich.console import Console
console = Console()
console.print(Panel("[bold cyan]Welcome![/bold cyan]", expand=False))
console.print(Panel("This is a simple panel"))
console.print(Panel.fit("[green]Fit to content[/green]"))
console.print(Panel("ASCII", border_style="ascii"))
console.print(Panel("Double", border_style="double"))
console.print(Panel("Rounded", border_style="rounded"))
Trees
Display hierarchical data:
from rich.tree import Tree
from rich.console import Console
console = Console()
tree = Tree("📁 project/")
tree.add("📄 README.md")
tree.add("📁 src/")
tree.add("📁 tests/")
subtree = tree.add("📁 lib/")
subtree.add("📄 utils.py")
console.print(tree)
Status Indicators
Show temporary status messages:
from rich.console import Console
console = Console()
with console.status("[bold cyan]Loading data...") as status:
do_time_consuming_work()
status.update("[bold green]Done!")
This displays a spinner while your code runs.
Live Updates
Use Live for real-time terminal updates:
from rich.live import Live
from rich.console import Console
console = Console()
with Live("Initializing...", console=console) as live:
for i in range(10):
live.update(f"Step {i+1}/10")
# Do work here
Combining Everything
Here’s a more complete example combining several features:
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
console = Console()
# Welcome panel
console.print(Panel.fit(
"[bold cyan]Welcome to MyApp v1.0[/bold cyan]",
border_style="cyan"
))
# Status table
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Component", style="cyan")
table.add_column("Status", justify="center")
table.add_row("Database", "[green]● Connected[/green]")
table.add_row("Cache", "[green]● Active[/green]")
table.add_row("API", "[yellow]● Rate limited[/yellow]")
console.print(table)
console.print()
console.print("[bold]Server running at[/bold] [link=http://localhost:8000]http://localhost:8000[/link]")
See Also
- typer-cli — Building CLIs with Typer
- argparse-guide — Building CLIs with Python’s standard library
- env-variables — Working with environment variables