nikkie-ftnextの日記

イベントレポートや読書メモを発信

Python でコンソールに色付きでロギングしたいときの選択肢、Rich の Logging Handler を触る

はじめに

七尾百合子さん、お誕生日 188日目 おめでとうございます! nikkieです。

色付きのロギング出力の素振りです。

目次

見なよ... Rich のハンドラを...

日本語 README より、「Logging Handler」
https://github.com/Textualize/rich/blob/v14.1.0/README.ja.md#logging-handler
画像を見るとカラフルな出力です。
これは手元でも再現できます。

% uv run --with rich python -m rich.logging

logging.pypython -mで実行1したときに、色付きの出力が例として見えるようになっています。
https://github.com/Textualize/rich/blob/v14.1.0/rich/logging.py#L242
(実際にサーバが起動したわけでなく、色付きログの出力例です)

実装はこちら

logging.basicConfig(
    level="NOTSET",
    format=FORMAT,
    datefmt="[%X]",
    handlers=[RichHandler(rich_tracebacks=True, tracebacks_show_locals=True)],
)

Rich の「Logging Handler」

rich.readthedocs.io

Rich supplies a logging handler which will format and colorize text written by Python’s logging module.

標準ライブラリ logging におけるハンドラは、ログメッセージを出力先に振り分ける役割を担います。
https://docs.python.org/ja/3/howto/logging.html#handlers
RichHandlerは、コンソールという出力先2に、Richの機能で色付きで出力するハンドラというわけですね。

https://github.com/Textualize/rich/blob/v14.1.0/rich/logging.py#L18 より

A logging handler that renders output with Rich. The time / level / message and file are displayed in columns.
The level is color coded, and the message is syntax highlighted.

日時、ログレベル、ログメッセージ、ファイルと4列表示です。

手元の既存のスクリプトで試してみました3
https://github.com/ftnext/python-logging-practice/blob/5f3cdf431ad53ad9f8ac3b780a8a342c161e0327/richhandler_example.py

% python script.py -v
[09/21/25 20:37:26] INFO     awesomelib:awesome - 想定通り                         __init__.py:9
                    WARNING  awesomelib:awesome - ちょっとヤバいよ                __init__.py:10

寄り道:basicConfig() の引数の formathandlers

basicConfig()が何をやっているのか、実装を読みました。
https://github.com/python/cpython/blob/v3.13.7/Lib/logging/__init__.py#L2004

logging.basicConfig(
    level=log_level,
    format="%(name)s:%(funcName)s - %(message)s",
    handlers=[RichHandler()],
)

結論から言うと、handlersの個々のハンドラに、formatインスタンス化されたFormatterがセットされています。

handlers = kwargs.pop("handlers", None)
# 省略
fs = kwargs.pop("format", _STYLES[style][1])
fmt = Formatter(fs, dfs, style)
for h in handlers:
    if h.formatter is None:
        h.setFormatter(fmt)

RichHandler()インスタンス化して渡して、どこでフォーマッタが適用されるのか不思議に思ったのですが、setFormatter()が呼び出されているなら納得です。

実験的に JSON フォーマッタ4に RichHandler の着色を組み合わせてみました(ただJSONが常に同じ色かも)

終わりに

Rich のドキュメントに見つけた RichHandler を素振りしました。
日時、ログレベル、ログメッセージ、ファイルの4列で、コンソールにカラフルにログ出力してくれます!
つけ外しだけでロギングの見た目を変えられるのが、個人的には好きです。


  1. 関連エントリ
  2. 引数consoleで指定できそうです。ref: https://github.com/Textualize/rich/blob/v14.1.0/rich/logging.py#L28-L29
  3. b:aの部分があたかもスライスのように誤ハイライトされるのは気になっています