python logging 指針
loggingの良い感じの使い方がイマイチわからなかったので、ネットの記事を漁って自分用の指針を作りました。
自分用ではありますが、loggingのプラクティスがわからん方の参考になれば幸いです。
ただ、この指針はバージョン1であり、完成度が高くないです。その点はご容赦いただると...。
(間違ってるところは指摘していただけると大変嬉しい)
指針
- 名前付きロガーでログ生成を行うこと。ルートロガーで生成しない。
- 不都合がない限りは、ファイル単位でロガーを用意すればいい。
- 原則、ハンドラーはルートロガーだけに追加する。
- 例外として、特定のロガー配下のログを別出力したい場合は、そのロガーにハンドラーを追加する
- 原則、「伝播なし(propagate=False)」は避けた方が良い。が、「4.」の場合や外部ライブラリのログがうるさい場合は設定してもよい。
- ログ出力のフォーマットは「
%(asctime)s - %(levelname)s:%(name)s:%(message)s
」にしておくと良い。 - ルートロガーを含めた全ロガーの細かい設定は、logging.iniファイルを使って行う。
- 原則、ルートロガー以外のロガーはデフォルト設定で良い。つまり、logging.iniファイルには、ルートロガー以外の設定を記載しなくてもいい。後に必要になったら、都度設定を追加していく。
指針の意図
1. について
ルートロガーで生成してはいけない。ロガー階層構造のメリットを得られなくなる。
logging.info
は、ルートロガーでログを生成してしまうので使わない方がいい。
import logging
logging.info('hogehoge')
import logging
logger = logging.getLogger(__name__)
logger.info('hogehoge')
2. について
複雑な状態を生まないよう出来るだけシンプルに努める。
とは言うものの、正直この指針は自信ない。
が、変に独自の名前付きルールを管理するよりシンプルで良さげだと見ている。
3. について
以下二つの性質を考えると、無闇やたらにハンドラーを追加しようとは思わないはず
- ログ出力はロガーに追加されてるハンドラーが行う
- ログは親に伝播し続けてルートロガーまで回る(propagateがTrueである限り)
つまり、あちこちのロガーにハンドラーを追加すると、同じようなログが大量に発生してしまう。
全てのログが最終的にルートロガーまで回るのだから、ルートに出力を任せちゃうのがシンプル。
4.について
とはいえ「このログは別の出力方法を採用したい(ex:別ファイルに記録したい)」と言う要求もある。
そういう限定的な出力を行いたいなら、個別のログにハンドラーを追加するほかない。
5. について
例えば「4.」の指針に従ったからと言って、ログの伝播が止まるわけではない。
ログは明示的に止められない限り伝播し続ける。
伝播を止めるためには、伝播を止めたいロガーにpropagate=False
の設定を行う必要がある。
6. について
結構一般的なフォーマットの形。
大体の記事やStackoverflowで、この4つの情報が載せられてる。
%(name)s
を%(filename)s
にしてるところもあるが、個人的には%(name)s
の方が好み。
この4つの情報があれば、いつどこでどのレベルのログが流れたのかをすぐ把握できる。
7. について
複数のロガーがある場合に有効。
ロガーのログレベルや、ハンドラーを設定する際、いちいち対象ロガーを探す必要がなくなる。
また、各ロガーの設定が一目見てわかるのも最高なポイント。
8. について
最初は特に、各ロガーの設定を気にしなくても良い。
ルートロガーの設定だけ気にしておけばOK。
「ロガーのログレベルをちゃんと考える必要があるんじゃ...」となるかもだが、必要になったタイミングで考えれば良い。
loggingの前提知識
- Loggerインスタンスがログ生成を行う
- Loggerインスタンスは親子構造になっており、ルートロガーを最上位の親にして下に名前付きロガーが連なっている
- あるLoggerインスタンスが生成したログは、親を辿ってルートロガーまで伝播する
- ログの出力(ex: 標準出社、ファイル出力)自体は、HandlerインスタンスがLoggerインスタンスに追加されてないとできない
- ログ出力のフォーマットはカスタム可能で、FormaterインスタンスをHandlerインスタンスに設定する必要がある
- あるLoggerインスタンスからの伝播を止めたい場合は、そのインスタンスのpropagateをFalseにすると良い
- Loggerインスタンスはシングルトンである。覚えておくと驚かずに済む。
参考記事
loggingの基本を図解で分かりやすく教えてくる
ルートロガーにだけハンドラーを追加すれば良いのだと教えてくれた
設定ファイルのことを教えてくれた
Discussion