Rich Pythonライブラリ:テーブル、プログレスバー、シンタックスハイライトでプロ級ターミナルUIを作る

Python tutorial - IT technology blog
Python tutorial - IT technology blog

Pythonスクリプトは動いているのに、出力は真っ黒な背景に白文字だけ、どこまで処理が進んでいるかわからない、エラーログと通常ログが混在している——そんな経験はないでしょうか?私もまったく同じ状況でした。最初200行だったautomationプロジェクトが今では2000行に膨れ上がり、その中で学んだ最も痛い教訓のひとつが:見づらいターミナル出力のせいでデバッグに倍の時間がかかるということです。

Richはまさにその問題を解決するために生まれました。このライブラリは現在、PyPIで月間5000万回以上ダウンロードされています——偶然ではありません。たった10分で、ターミナルの見た目ががらりと変わります。

5分ですぐ動かす

インストール:

pip install rich

動作確認 — このコマンドを実行して、ターミナルがカラー表示に対応しているか確認しましょう:

python -m rich

カラフルな出力が表示されれば問題ありません。では、print()をRichに置き換えてみましょう:

from rich import print
from rich.console import Console

console = Console()

# 色付き・太字・斜体で出力 — HTMLライクなマークアップを使用
console.print("[bold green]✓ デプロイ成功![/bold green]")
console.print("[red]✗ データベース接続エラー[/red]")
console.print("[yellow]⚠ 警告: ディスク使用率 85%[/yellow]")

実行してみてください——緑、赤、黄色がすぐに表示されます。次のセクションでは、実際のスクリプトで毎日使っている機能を紹介します。

テーブル表示 — 手動での列揃えから解放される

以前はf"{col1:<20}{col2:<15}"で列を揃えていました。見た目が悪く、データが長いと崩れる。Rich Tableがこれをすっきり解決します:

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

console = Console()

table = Table(title="サーバーステータス", show_header=True, header_style="bold cyan")

table.add_column("Server", style="dim", width=20)
table.add_column("CPU %", justify="right", style="green")
table.add_column("RAM %", justify="right", style="yellow")
table.add_column("Status", justify="center")

table.add_row("web-01.prod", "23%", "67%", "[green]● Online[/green]")
table.add_row("web-02.prod", "45%", "82%", "[green]● Online[/green]")
table.add_row("db-01.prod", "78%", "91%", "[red]⚠ High Load[/red]")
table.add_row("backup-01", "5%", "34%", "[yellow]○ Standby[/yellow]")

console.print(table)

Tableは自動で列を揃え、ボーダーを描き、ターミナルが狭いとテキストを自動折り返しします。このパターンをすべてのmonitoringスクリプトで使っています——生のJSONを眺めるより、はるかに見やすくなりました。

条件に応じた動的な色付け

def cpu_style(value: int) -> str:
    if value > 80:
        return f"[bold red]{value}%[/bold red]"
    elif value > 60:
        return f"[yellow]{value}%[/yellow]"
    return f"[green]{value}%[/green]"

table.add_row("web-01", cpu_style(23), "67%", "[green]● Online[/green]")
table.add_row("db-01", cpu_style(91), "91%", "[red]⚠ High Load[/red]")

プログレスバー — スクリプトの進捗を把握する

バッチ処理スクリプトにプログレスバーがないと、実行中なのかフリーズしているのかが本当にわかりません。以前、約20分待ってからスクリプトが最初からクラッシュしていたことに気づいたことがありました——CPUが0%なのに、バックグラウンドで処理中だと思い込んでいたのです。

from rich import print
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn, TimeRemainingColumn
import time

files = [f"file_{i}.log" for i in range(50)]

with Progress(
    SpinnerColumn(),
    TextColumn("[progress.description]{task.description}"),
    BarColumn(),
    TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
    TimeRemainingColumn(),
) as progress:
    task = progress.add_task("ログファイルを処理中...", total=len(files))
    
    for file in files:
        # 実際のファイル処理をここに記述
        time.sleep(0.05)  # 処理のシミュレーション
        progress.update(task, advance=1, description=f"処理中: {file}")

print("[bold green]✓ 完了![/bold green]")

Richは直近の進捗から処理速度を自動計算し、残り時間をかなり正確に予測します。10GBのmigrationを実行しながら「あと約3分で完了」とわかる——ただ画面を見つめて待つのとは大違いです。

複数タスクを並行実行する

with Progress() as progress:
    task_download = progress.add_task("Download...", total=100)
    task_process  = progress.add_task("Process...", total=200)
    task_upload   = progress.add_task("Upload...", total=50)

    while not progress.finished:
        progress.update(task_download, advance=0.9)
        progress.update(task_process, advance=1.1)
        progress.update(task_upload, advance=0.5)
        time.sleep(0.02)

シンタックスハイライト — ターミナルで直接コードをデバッグ

単色のJSON rawを見てAPIレスポンスをデバッグすると、フィールドを見落としがちです。Syntaxを使ってconfigファイル、SQLクエリ、JSONレスポンスをハイライトすると——問題箇所をはるかに素早く見つけられます:

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

console = Console()

# Pythonコードをハイライト表示
python_code = '''
def check_server_health(host: str, port: int = 80) -> dict:
    import socket
    try:
        sock = socket.create_connection((host, port), timeout=3)
        sock.close()
        return {"status": "online", "host": host}
    except socket.timeout:
        return {"status": "timeout", "host": host}
    except ConnectionRefusedError:
        return {"status": "offline", "host": host}
'''

syntax = Syntax(python_code, "python", theme="monokai", line_numbers=True)
console.print(syntax)
# JSONをハイライト — APIレスポンスのデバッグに最適
import json
from rich.syntax import Syntax

api_response = {
    "status": "success",
    "data": {"user_id": 42, "role": "admin"},
    "timestamp": "2026-11-15T09:30:00Z"
}

json_str = json.dumps(api_response, indent=2, ensure_ascii=False)
syntax = Syntax(json_str, "json", theme="github-dark")
console.print(syntax)

よく使われるテーマ:monokai(目に優しいダーク背景)、github-dark(VS Code風)、dracula、one-dark。python -m rich.syntaxを実行すると、さらに多くのオプションを確認できます。

応用:Panel、Tree、Live Display

これら3つのコンポーネントは毎日使う必要はありませんが、必要なときに代替がきかないものです。

Panel — 重要な情報を枠で囲む

エラーメッセージが何百行ものログに埋もれる代わりに、Panelで囲めば見逃すことがありません:

from rich.panel import Panel
from rich.text import Text

# 目立つエラー表示 — 通常のログに埋もれない
error_msg = Text()
error_msg.append("ConnectionError: ", style="bold red")
error_msg.append("db-01.prod:5432 に接続できません
", style="red")
error_msg.append("確認事項: ファイアウォールルール、pg_hba.conf、ネットワーク", style="yellow")

console.print(Panel(error_msg, title="[bold red]✗ 重大なエラー[/bold red]", border_style="red"))

Tree — ディレクトリ構造や依存関係を表示する

サーバートポロジーやインフラ構造を可視化——行ごとに出力するよりはるかに明確です:

from rich.tree import Tree

tree = Tree("[bold]production[/bold] 🖥")
web = tree.add("[green]web servers[/green]")
web.add("web-01 (nginx 1.24, PHP 8.2)")
web.add("web-02 (nginx 1.24, PHP 8.2)")
db = tree.add("[blue]databases[/blue]")
db.add("db-master (PostgreSQL 16)")
db.add("db-replica (PostgreSQL 16, lag: 0.1s)")
tree.add("[yellow]load balancer[/yellow] (HAProxy 2.8)")

console.print(tree)

Live — 画面を消去せずリアルタイム更新

テーブルをリアルタイムで更新しながら画面をクリアしない——継続的にmetricsを監視するdashboardが必要なときに使います:

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

def generate_metrics_table(tick: int) -> Table:
    table = Table(title=f"Server Metrics — Refresh #{tick}")
    table.add_column("Server")
    table.add_column("CPU")
    table.add_column("Connections")
    
    import random
    for i in range(1, 4):
        cpu = random.randint(10, 95)
        style = "red" if cpu > 80 else "green"
        table.add_row(f"web-0{i}", f"[{style}]{cpu}%[/{style}]", str(random.randint(50, 500)))
    
    return table

with Live(generate_metrics_table(0), refresh_per_second=1) as live:
    for tick in range(20):
        time.sleep(1)
        live.update(generate_metrics_table(tick))

実プロジェクトから学んだ実践的なTips

automationプロジェクトが200行から2000行に膨れ上がる中で学んだ——Richを正しく使うためのポイントです:

  • Consoleは一度だけ作成し、どこでも使う — Console()を何度も初期化しないでください。専用モジュール(console.py)で作成し、必要な場所でimportする。
  • ログファイルに色は不要 — Console(file=log_file, highlight=False)を使ってANSIコードなしでログを書き込む。catで読んでも余分な文字が入らない。
  • パイプ時は自動で色をオフ — Richはoutputがパイプされたとき(python script.py | grep error)を自動検出し、カラーを無効化します。手動で処理する必要はありません。
  • 標準loggingとの組み合わせ — Richにはloggingモジュールと統合できるRichHandlerがあります:
import logging
from rich.logging import RichHandler

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

log = logging.getLogger("rich")
log.info("Server started")
log.warning("ディスク使用率が高い: 87%")
log.error("Database connection failed")
  • Rich Traceback — スクリプトの先頭に追加することで、スタックトレースが見やすくなります:
from rich.traceback import install
install(show_locals=True)  # show_locals=True でエラー箇所の変数値を表示

Richのオーバーヘッドはprint一回あたり1ms未満——心配する必要はありません。サーバーmonitoringスクリプト、CI pipeline、data migrationツールに適用することで、出力に色と構造があるだけでデバッグが格段に速くなります。覚えておくことはひとつ:色を楽しみのためだけに追加しないこと。緑はsuccess、赤はerror、黄色はwarning——それで十分です。

Share: