Pythonのloggingについて基本的な部分を確認する

Pythonのloggingについてloggerの定義方法の種類や、Formatterの出力できる項目等の基本的な項目について確認してみました。
2023.12.15

DA事業本部の横山です。

今回は。普段から利用しているPythonloggingについてなんとなくで理解している部分が多かったため、基本的なことから復習したので確認した内容を共有します。

前提条件

本記事で利用しているPythonのバージョンは以下になります。

  • Python: 3.8.13

確認した内容

今回は、以下の項目について公式ドキュメントを中心に確認を行いました。

  • ログレベル
  • loggerの定義方法の種類
  • 設定ファイル形式
  • Formatter

一番簡単な利用例

import logging
logging.warning('Watch out!')  # will print a message to the console
logging.info('I told you so')  # will not print anything
WARNING:root:Watch out!

ログレベル

レベル いつ使うか
DEBUG おもに問題を診断するときにのみ関心があるような、詳細な情報。
INFO 想定された通りのことが起こったことの確認。
WARNING 想定外のことが起こった、または問題が近く起こりそうである (例えば、'disk space low') ことの表示。
ERROR より重大な問題により、ソフトウェアがある機能を実行できないこと。
CRITICAL プログラム自体が実行を続けられないことを表す、重大なエラー。

普段利用しているログレベルは、DEBUG,INFO,WARNING,ERRORCRITICALを使うことはほぼない気がします。これはプロジェクト毎のログ設計次第ではありますが、各ログレベルがどういった状況で利用されるのかは意識して使い分ける必要がありますね。

loggerの定義方法

  1. 設定用のメソッドを呼び出す。Python コードを明示的に使って、ロガー、ハンドラ、そしてフォーマッタを生成する。
    • ハードコードになり柔軟性に書けるため避けたい
  2. ロギング設定ファイルを作り、それを fileConfig() 関数を使って読み込む。
    • configparser形式(≒INIファイル)で記述する必要がある
    • よく見かけるスタイルではあるが、可読性には欠ける
  3. 設定情報の辞書を作り、それを dictConfig() 関数に渡す。
    • 設定ファイルに基づく方法の上位版としてPython3.2から提供され、推奨されている模様
    • 辞書化さえできれば渡せるので、JSON,YAML,TOML等 設定ファイルの形式は選ばない

Logging HOWTO Logging CookBook configparser 環境設定辞書スキーマ

以上からdictConfig()用いた実装が推奨されており、設定ファイルを何らかの形で辞書として読み込んでdictConfig()に渡してあげるのがよさそうです。

設定ファイル形式

ここからは、dictConfig()を利用する前提で、その設定辞書を記述する設定ファイルの形式について考えていきます。

  1. configparser
    • この形式であればfileConfig()使えばいい
  2. JSON
    • 標準ライブラリでパース可能、大多数の人が触ったことがある
  3. YAML
    • 外部ライブラリが必要、JSONと比べ記述量が少なく可読性が高い
  4. TOML
    • Python3.11から標準ライブラリでパース可能
    • 外部ライブラリが必要となるが、将来的にパーサーが追加されるのは標準らしさがある
特徴 YAML JSON TOML
キーと値の区切り文字 :(コロン) :(コロン) =
コメントが書ける 書ける 書けない 書ける
日付型の有無 有り 無し 有り
null値の有無 有り 有り 無し
構造化データの表現 インデントを使用 データの最初と最後を波括弧で括る 角括弧やドットを使用

tomllib TOML v1.0.0-rc.2

私が経験したことがあるのは、fileConfig()を利用した際のconfigparser、またはdictConfig()を利用した際のTOMLになります。

ここに関しては、Python3.11以降ではパーサーが標準化されることもありTOMLで記述することに慣れていきたいですね。

Formatter

私が業務上よく利用するのはLambdaやGlue jobなのですが、それらにおいてログ出力された内容がどのソースから出力されたかを同定するには以下のような項目が必要となります。

  • 出力項目
    • 時刻
    • スクリプト名
    • 関数名
    • 行番号
    • ログレベル
    • メッセージ
  • 出力する必要があるかケースバイケースのもの
    • プロセスID
    • プロセス名
    • スレッドID
    • スレッド名

まずは以下のようなフォーマット内容で出力しておけば、最低限困らなそうです。

%(asctime)s %(name)s %(funcName)s %(lineno)-3d [%(levelname)] %(message)s

LogRecord 属性

おわりに

今回は、Pythonloggingについてなんとなくで理解している部分が多かったため、基本的なことから復習してみました。 特にloggerの設定方法の違いや、Formatterで出力できる項目など普段なんとなくで理解していた部分について整理できたと思います。

以上になります。この記事がどなたかの助けになれば幸いです。