跳转至

Rich Python 美化输出

为什么要学 Rich

Rich 是 Python 的终端美化输出库,能够在终端中渲染丰富的格式:表格、Markdown、语法高亮、进度条、树形结构、面板等。它让你的 CLI 工具和脚本输出从单调的纯文本变成专业美观的界面。Rich 已经成为 Python 社区中最流行的终端输出库,被 Textual、FastAPI、Prefect 等知名项目广泛使用。


核心概念

概念白话解释用途
Console控制台Rich 输出的核心对象
Markup标记语法类似 BBCode 的内联样式
Table表格美观的终端表格
Panel面板带边框的内容区域
Progress进度条任务进度显示
Tree树形结构层级数据展示
Syntax语法高亮代码着色

安装配置

pip install rich

快速上手

from rich import print
from rich.console import Console

# 基础美化打印(替代内置 print)
print("[bold green]成功![/bold green] 任务已完成。")
print("[red]错误:[/red] 文件不存在。")
print("[blue underline]https://example.com[/blue underline]")

# Console 对象
console = Console()
console.print("Hello", style="bold red")
console.print("World", style="italic blue on white")

# 打印 Python 对象(自动美化)
data = {"name": "Alice", "age": 30, "skills": ["Python", "Go", "Rust"]}
console.print(data)

# 日志式输出
console.log("开始处理...")
console.log("[bold]完成[/bold]", log_locals=True)

# 规则线
console.rule("[bold red]分隔线[/bold red]")

表格

from rich.table import Table

table = Table(title="语言对比")
table.add_column("语言", style="cyan", no_wrap=True)
table.add_column("类型", style="magenta")
table.add_column("速度", justify="right", style="green")

table.add_row("Python", "解释型", "⭐⭐")
table.add_row("Go", "编译型", "⭐⭐⭐⭐")
table.add_row("Rust", "编译型", "⭐⭐⭐⭐⭐")

console.print(table)

进度条

from rich.progress import Progress
import time

with Progress() as progress:
    task1 = progress.add_task("[red]下载中...", total=100)
    task2 = progress.add_task("[green]处理中...", total=200)

    while not progress.finished:
        progress.update(task1, advance=1)
        progress.update(task2, advance=2)
        time.sleep(0.02)

进阶用法

Markdown 渲染

from rich.markdown import Markdown

md = Markdown("""
# 标题
## 子标题

- 列表项 1
- 列表项 2

```python
print("Hello")

引用文本

名称
A1
""")
console.print(md)
### 语法高亮

```python
from rich.syntax import Syntax

code = '''
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
'''

syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
console.print(syntax)

# 从文件读取
syntax = Syntax.from_path("main.py", line_numbers=True, line_range=(10, 30))
console.print(syntax)

树形结构

from rich.tree import Tree

tree = Tree("📁 项目")
src = tree.add("📁 src")
src.add("📄 main.py")
src.add("📄 utils.py")
tests = tree.add("📁 tests")
tests.add("📄 test_main.py")
tree.add("📄 README.md")
tree.add("📄 pyproject.toml")

console.print(tree)

面板和布局

from rich.panel import Panel
from rich.layout import Layout
from rich.columns import Columns

# 面板
panel = Panel("面板内容", title="标题", subtitle="副标题", border_style="green")
console.print(panel)

# 布局
layout = Layout()
layout.split_column(
    Layout(name="header", size=3),
    Layout(name="body"),
    Layout(name="footer", size=3),
)
layout["body"].split_row(
    Layout(name="left"),
    Layout(name="right", ratio=2),
)
layout["header"].update(Panel("Header"))
layout["left"].update(Panel("Left"))
layout["right"].update(Panel("Right"))
layout["footer"].update(Panel("Footer"))
console.print(layout)

实时显示

from rich.live import Live
from rich.table import Table
import time

def generate_table(data):
    table = Table()
    table.add_column("指标")
    table.add_column("值")
    for k, v in data.items():
        table.add_row(k, str(v))
    return table

with Live(generate_table({}), refresh_per_second=4) as live:
    for i in range(100):
        data = {"进度": f"{i}%", "速度": f"{i*10} MB/s", "时间": f"{i*0.1:.1f}s"}
        live.update(generate_table(data))
        time.sleep(0.1)

异常美化

from rich.traceback import install

# 全局安装美化异常
install(show_locals=True)

# 之后所有未捕获的异常都会以 Rich 格式显示
# 包括语法高亮、局部变量值等

与 logging 集成

from rich.logging import RichHandler
import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(message)s",
    datefmt="[%X]",
    handlers=[RichHandler(rich_tracebacks=True)]
)

log = logging.getLogger("my_app")
log.info("服务启动")
log.warning("磁盘空间不足")
log.error("连接失败")

常见问题

Q: 在 CI/CD 中颜色乱码?

# 检测是否在终端
console = Console(force_terminal=True)  # 强制启用
console = Console(no_color=True)        # 强制禁用颜色

Q: 输出到文件?

console = Console(file=open("output.txt", "w"))
console.print("[bold]Hello[/bold]")  # 自动去除格式化

# 或保留格式
console = Console(record=True)
console.print("[bold]Hello[/bold]")
html = console.export_html()
text = console.export_text()

Q: 与 click/typer 配合?

两者完美兼容。在 click/typer 的回调中使用 Rich 输出即可。


参考资源

  • GitHub:https://github.com/Textualize/rich
  • 文档:https://rich.readthedocs.io/
  • 示例:https://github.com/Textualize/rich/tree/master/examples
  • Rich CLI:https://github.com/Textualize/rich-cli