132. Rich
Beautiful terminal output with Rich
132. Rich
๐จ Aryan wants the RAM manager to show a color-coded table of processes in the terminal โ red for high RAM, yellow for medium, green for low. His Rich table is missing columns and uses the wrong color threshold logic.
๐ก Fun fact: Rich was created by Will McGugan and first released in 2019. Within two years it became one of the most-starred Python projects on GitHub. The key insight: terminals have supported ANSI color codes since the 1970s, but nobody had made a library that made them actually easy to use. Rich renders markdown, syntax-highlighted code, progress bars, and tables โ all in your terminal.
โ ๏ธ Watch out: Rich uses square-bracket markup [red]text[/red], NOT HTML-style <red>text</red>. If you use angle brackets, Rich will try to render them as markup and either silently fail or display the literal <red> tags. This is the single most common Rich mistake.
๐ค Think about it: The color logic is semantic: high RAM is a warning (red), low RAM means everything is fine (green). This matches traffic lights, status LEDs, and every monitoring dashboard on the planet. When you see a reversed color scheme in code, what does that tell you about whether the developer tested their work?
Learning objectives
- Use add_column() with positional title argument
- Apply Rich markup [color]text[/color] for colored output
- Use correct threshold logic (high = red, low = green)
- Add rows with positional string arguments to add_row()
- Print tables with console.print()
Key concepts
- rich.console.Console โ styled terminal output
- rich.table.Table โ tabular data display
- Rich markup โ [color]โฆ[/color] syntax
- add_column(title) โ positional title argument
- add_row(*values) โ positional string arguments
- box styles โ ROUNDED, SIMPLE, HEAVY
Try it
Concept detail
Beautiful Terminal Output with Rich
pip install rich โ colors, tables, progress bars, and more.
Console
from rich.console import Console
console = Console()
console.print('[bold red]Error![/bold red] Something went wrong.')
console.print('[green]โ[/green] Operation succeeded.')
console.print('Normal text with [cyan]colored[/cyan] section.')Markup format
[red]text[/red] โ color
[bold]text[/bold] โ bold
[italic]text[/italic] โ italic
[bold red]text[/] โ combined, [/] closes allTables
from rich.table import Table
from rich import box
table = Table('Name', 'Value', box=box.ROUNDED)
# OR:
table = Table(box=box.SIMPLE)
table.add_column('Name', style='cyan', justify='left')
table.add_column('Value', justify='right')
table.add_row('RAM', '[red]87%[/red]')
table.add_row('Swap', '[green]12%[/green]')
console.print(table)Useful box styles
box.ROUNDED # โญโโโโโโฎ
box.SIMPLE # minimal lines
box.HEAVY # bold lines
box.MARKDOWN # compatible with markdown tablesColor logic for monitoring
def ram_color(percent: float) -> str:
if percent > 80: return 'red'
if percent > 60: return 'yellow'
return 'green'Solution
from rich.console import Console
from rich.table import Table
from rich import box
console = Console()
def make_process_table(processes: list[dict]) -> Table:
"""Create a Rich table showing top processes with color coding."""
table = Table(title='Top Processes', box=box.ROUNDED)
table.add_column('Process', style='cyan')
table.add_column('PID', justify='right')
table.add_column('RSS (MB)', justify='right')
table.add_column('Status', justify='center')
for proc in processes:
rss = proc['rss_mb']
# High RAM = red warning, low RAM = green (all good)
if rss > 500:
color = 'red'
elif rss > 100:
color = 'yellow'
else:
color = 'green'
status = '๐ด High' if rss > 500 else ('๐ก Med' if rss > 100 else '๐ข Low')
table.add_row(
proc['name'],
str(proc['pid']),
f'[{color}]{rss:.1f}[/{color}]',
status,
)
return table
def print_ram_summary(percent: float, used_gb: float, total_gb: float):
"""Print a color-coded RAM usage summary line."""
color = 'red' if percent > 80 else ('yellow' if percent > 60 else 'green')
console.print(f'[{color}]RAM: {percent:.1f}% ({used_gb:.1f}/{total_gb:.1f} GB)[/{color}]')Tests
from io import StringIO
from rich.console import Console
PROCS = [
{'name': 'chrome', 'pid': 100, 'rss_mb': 800.0},
{'name': 'python', 'pid': 200, 'rss_mb': 150.0},
{'name': 'vim', 'pid': 300, 'rss_mb': 30.0},
]
def test_table_has_four_columns():
table = make_process_table(PROCS)
assert len(table.columns) == 4
def test_table_has_correct_rows():
table = make_process_table(PROCS)
assert table.row_count == 3
def test_high_rss_shows_red():
table = make_process_table(PROCS)
buf = StringIO()
c = Console(file=buf, highlight=False, markup=True)
c.print(table)
output = buf.getvalue()
# High RAM (chrome, 800 MB) should show red, not green
assert 'red' in output.lower() or '๐ด' in output, (
'Process with >500 MB RSS should show red/๐ด, not green'
)
def test_low_rss_shows_green():
table = make_process_table(PROCS)
buf = StringIO()
c = Console(file=buf, highlight=False, markup=True)
c.print(table)
output = buf.getvalue()
assert 'green' in output.lower() or '๐ข' in output, (
'Process with <100 MB RSS should show green/๐ข'
)
def test_print_ram_summary_uses_rich_markup():
import inspect
src = inspect.getsource(print_ram_summary)
# Must use [color]...[/color] bracket syntax, not <color>...</color> HTML tags
assert '<red>' not in src and '<green>' not in src and '<yellow>' not in src, (
'Rich markup uses [color]text[/color] square brackets, not <color> HTML tags'
)
assert '[' in src, 'Must use Rich markup with square brackets: [color]text[/color]'
def test_print_ram_summary_no_html_tags():
# Capture output by patching the global console object
buf = StringIO()
test_console = Console(file=buf, highlight=False, markup=True)
import unittest.mock as mock
# Replace the global 'console' used inside print_ram_summary
import sys
module = sys.modules[__name__]
with mock.patch.object(module, 'console', test_console):
print_ram_summary(85.0, 6.8, 8.0)
output = buf.getvalue()
assert '<red>' not in output, 'Output must not contain HTML-style <red> tags'
def test_print_ram_summary_high_ram_outputs_red():
import inspect
src = inspect.getsource(print_ram_summary)
# The logic should map percent > 80 to 'red'
assert 'red' in src, 'High RAM (>80%) must use red color in markup'
def test_print_ram_summary_low_ram_outputs_green():
import inspect
src = inspect.getsource(print_ram_summary)
# The logic should map low percent to 'green'
assert 'green' in src, 'Low RAM must use green color in markup'