登場人物
Loggerクラス : loggingの主体のはこいつ。ログの生成から目的の場所まで送るまでを管理する。Loggerクラスから生成されるオブジェクト毎にHandlerやFilterを設定できる。Loggerは階層構造(後述)をとり、継承により親の設定を引き継ぐ。
root (rootLoggerオブジェクト) : デフォルトのLoggerクラスのオブジェクトであり全てのロガーの親。必ず1つ。logging.info()
等で書かれるログは全てここに流れる。
独自のLoggerオブジェクト : getLogger("ロガー名")
により生成する独自のLoggerクラスのオブジェクト。ファイル毎に作成することでどのファイルのログかが明示的にわかり、それぞれにログレベルの設定やハンドラを設定できる。階層構造を作ることが可能(後述)。
LogRecord : ログ本文。Loggerにより生成される。
Handler : LogRecordをどこに届けるか(標準出力やファイル書込み、HTTPリクエストなど)を管理する。Loggerに指定する。
→ 種々のハンドラ:https://docs.python.org/ja/3/howto/logging.html#useful-handlers
Formatter : ログのフォーマットを指定。Handlerに指定する。
Filter : どのログを出力するかの管理。LoggerもしくはHandlerに指定。
Loggerの階層構造
Loggingのフロー
上の階層構造のmod2
とmod2.fuga
を用いてロギングのフローを確認する。
https://docs.python.org/ja/3/howto/logging.html#logging-flow
import logging
import loggingtest2
logger = logging.getLogger("mod2")
logger.setLevel(logging.DEBUG)
# フォーマット生成
formatter = logging.Formatter('parent: %(name)s [%(levelname)s] %(message)s')
# 標準エラー出力のハンドラ生成
handler = logging.StreamHandler()
# ハンドラへの各種設定
handler.setLevel(logging.ERROR)
handler.setFormatter(formatter)
# ロガーにハンドラをアタッチ
logger.addHandler(handler)
if __name__ == "__main__":
loggingtest2.test()
import logging
def test():
logger = logging.getLogger("mod2.fuga")
logger.setLevel(logging.DEBUG)
# フォーマット生成
formatter = logging.Formatter('child: %(name)s [%(levelname)s] %(message)s')
# ハンドラ生成・設定
handler = logging.StreamHandler()
handler.setLevel(logging.WARNING)
handler.setFormatter(formatter)
logger.addHandler(handler)
#logger.propagate = False #後述
logger.error("bbb")
この状態で実行すると、親のハンドラからも子のハンドラからも出力される。
$ python loggingtest.py
child: mod2.fuga [ERROR] bbb
parent: mod2.fuga [ERROR] bbb
他も試すとわかるが、loggingtest2.pyのハンドラの条件を"CRITICAL"以上に設定すればchild:~~
は出力されなくなり、getLogger()
のドットを外し、階層構造をフラットにすると親だったmod2のハンドラは呼ばれなくなるためchild:~~
だけが出力される。
propagate属性
propagateの直訳は「伝播する」であり、この属性はLogRecordを親へ伝播させるかを指定する。
上のコードでlogger.propagate = False
をアンコメントすることで親が呼ばれないことが確認できる。
ロギングの設定の外だし
loggingに対する設定はlogging.conf
という別ファイルに記述し、fileConfig()
で読み出すことが可能。これによりロギングの設定部分を処理本体から切り離すことができる。詳細は公式ドキュメント参照。