Pythonのloggingモジュールについては過去の記事で書かれていますが、その後の勉強でいろいろと分かったことがありました。
多少ハマってしまったこともあったため、ここにまとめてみたいと思います。
1.設定ファイルの作り方
2.設定ファイルで設定してみる
3.設定ファイルを書くときの注意
4.おまけ
多少ハマってしまったこともあったため、ここにまとめてみたいと思います。
1.設定ファイルの作り方
2.設定ファイルで設定してみる
3.設定ファイルを書くときの注意
4.おまけ
1.設定ファイルの作り方
設定ファイルとは
loggingモジュールをインポートした直後は "root" ロガー以外は設定が行われていません。そのため
log = logging.getLogger("mylogger")
log.debug("hello, logging module!")
と打ち込んでも、どこに書き込めばいいのか、どのレベル以上のログを扱うのかといった設定を "mylogger" に対して何も行っていないため
画面はおろか、ファイルにも "hello, logging module!" のログは書き込まれません。
そこで、書き込み先や出力レベルなどを設定する必要があります。
たとえば、先ほどの "mylogger" にdebug以上のレベルのログを画面に書き込む設定を行ってみましょう。
log.setLevel(logging.DEBUG) # debug以上のレベルのログを書き込む
# 書き込み先や、ログの出力フォーマットを決める "handler" を作る
handler = logging.StreamHandler(sys.stdout) # 標準出力にログを書き込む
handler.setFormatter(logging.Formatter("%(asctime)s %(message)s")) # 出力フォーマットを設定
# "mylogger" に "handler" を通してログ出力できるようにする
log.addHandler(handler) # "mylogger" に "handler" を追加
さあ、これで準備は整いました。さっそく挨拶をしてみましょう。
log.debug("hello, logging module!")
2008-10-23 00:48:31,864 hello, logging module!
表示されましたでしょうか?
"root" ロガーは最初からこのような設定が済んでいるために
rootlog = logging.getLogger("root")
rootlog.warn("hello, root logger!")
WARNING:root:hello, root logger!
と "handler" の設定を行わなくても表示させることができますが、新しいロガーを作るときはこのような設定を行う必要があります。
2.設定ファイルで設定してみる
formatter、handler、loggerの3つの要素についての設定を行っています。
[formatter_...]
ログのフォーマットを設定します。
%(asctime)s などを使ってどんな情報をログに書き込むかを決めていきます。
datefmt= は、%(asctime)s の形式を決めるものです。
http://www.python.jp/doc/release/lib/module-time.html に、どんなものが使えるかが載っています。
[handler_...]
ハンドラの設定を行います。
ログの出力先を決めたり、使用するフォーマットを決める部分です。
[logger_...]
ロガーの設定を行います。
ログの出力レベルや、使用するハンドラ、ロガーを取得するときの名前を設定します。
親子関係を持ったロガーの場合、子のロガーで書き込んだログが親のロガーでも出力されます。
その機能を使うかどうかの設定を propagate で行います。上位のロガーでも同じ内容を書き出したいときは
propagate = 1
と設定します。
3.設定ファイルを書くときの注意
実際に私が設定ファイルを書いているときに嵌ったことをいくつかあげておきます。
1. 設定ファイルには必ず "root" ロガーの設定を行う
最初から設定が行われている "root" ロガー。設定ファイルにまで書かなくてもいいだろう、その分減って見やすくなるし。
...そう思い、 "root" ロガーの設定を行わずに設定ファイルを書き、loggingの実験を行いました。
そのときの私は、まさかそんなことで2時間も悩むことになるとは思いもしませんでした。
2.args=(sys.stdout,) の ',' を忘れない
インタープリタ上では
StreamHandler(sys.stdout)
で動きますが、設定ファイルに書き込む際には(sys.stdout,)としなければ
エラーになってしまいます。
タプルになるように書かないといけないのではないかと思います。
実はライブラリリファレンスに書いてあることばかりだったりします。
やっぱり困ったときは基本に立ち返ることも重要ですね。
4.おまけ
設定ファイルのひな形
面倒なrootロガーの設定を済ませたものを載せておきます。
DEBUGレベル以上のログを画面に出力する設定になっています。
これに、使いたいロガーの設定を付け足していけば設定ファイルが出来上がります。
[loggers]
keys=root
[formatters]
keys=default
[handlers]
keys=default
[formatter_default]
format=%(asctime)s %(name)s %(levelname)s %(message)s
datefmt=
[handler_default]
class=StreamHandler
formatter=default
args=(sys.stdout,)
[logger_root]
level=DEBUG
handlers=default
設定ファイルとは
loggingモジュールをインポートした直後は "root" ロガー以外は設定が行われていません。そのため
log = logging.getLogger("mylogger")
log.debug("hello, logging module!")
と打ち込んでも、どこに書き込めばいいのか、どのレベル以上のログを扱うのかといった設定を "mylogger" に対して何も行っていないため
画面はおろか、ファイルにも "hello, logging module!" のログは書き込まれません。
そこで、書き込み先や出力レベルなどを設定する必要があります。
たとえば、先ほどの "mylogger" にdebug以上のレベルのログを画面に書き込む設定を行ってみましょう。
log.setLevel(logging.DEBUG) # debug以上のレベルのログを書き込む
# 書き込み先や、ログの出力フォーマットを決める "handler" を作る
handler = logging.StreamHandler(sys.stdout) # 標準出力にログを書き込む
handler.setFormatter(logging.Formatter("%(asctime)s %(message)s")) # 出力フォーマットを設定
# "mylogger" に "handler" を通してログ出力できるようにする
log.addHandler(handler) # "mylogger" に "handler" を追加
さあ、これで準備は整いました。さっそく挨拶をしてみましょう。
log.debug("hello, logging module!")
2008-10-23 00:48:31,864 hello, logging module!
表示されましたでしょうか?
"root" ロガーは最初からこのような設定が済んでいるために
rootlog = logging.getLogger("root")
rootlog.warn("hello, root logger!")
WARNING:root:hello, root logger!
と "handler" の設定を行わなくても表示させることができますが、新しいロガーを作るときはこのような設定を行う必要があります。
2.設定ファイルで設定してみる
新しいロガーを使えるようになるまでの流れをまとめてみました。
import logging
import sys
log = logging.getLogger("mylogger")
log.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter("%(asctime)s %(message)s"))
log.addHandler(handler)
大した量のコードではありませんが、ロガーを新しく作るたびにこんなコードを書くのは面倒です。
そこで、設定ファイルを使うことでこの面倒なコードのコピペから脱出しましょう。
上のコードと同じ設定を行うときの設定ファイルは以下のようになります。
[loggers]
keys=root,mylogger
keys=root,mylogger
[handlers]
keys=roothandler,myhandler
keys=roothandler,myhandler
[formatters]
keys=default,myformat
keys=default,myformat
[formatter_default]
format=%(asctime)s %(levelname)s %(message)s
datefmt=
format=%(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_myformat]
class=logging.Formatter
format=%(asctime)s %(message)s
datefmt=
class=logging.Formatter
format=%(asctime)s %(message)s
datefmt=
[handler_roothandler]
class=StreamHandler
args=(sys.stdout,)
formatter=default
class=StreamHandler
args=(sys.stdout,)
formatter=default
[handler_myhandler]
class=StreamHandler
args=(sys.stdout,)
formatter=myformat
class=StreamHandler
args=(sys.stdout,)
formatter=myformat
[logger_root]
level=DEBUG
handlers=roothandler
level=DEBUG
handlers=roothandler
[logger_mylogger]
level=DEBUG
handlers=myhandler
propagate=0
qualname=mylogger
</pre>
level=DEBUG
handlers=myhandler
propagate=0
qualname=mylogger
</pre>
formatter、handler、loggerの3つの要素についての設定を行っています。
[formatter_...]
ログのフォーマットを設定します。
%(asctime)s などを使ってどんな情報をログに書き込むかを決めていきます。
datefmt= は、%(asctime)s の形式を決めるものです。
http://www.python.jp/doc/release/lib/module-time.html に、どんなものが使えるかが載っています。
[handler_...]
ハンドラの設定を行います。
ログの出力先を決めたり、使用するフォーマットを決める部分です。
[logger_...]
ロガーの設定を行います。
ログの出力レベルや、使用するハンドラ、ロガーを取得するときの名前を設定します。
親子関係を持ったロガーの場合、子のロガーで書き込んだログが親のロガーでも出力されます。
その機能を使うかどうかの設定を propagate で行います。上位のロガーでも同じ内容を書き出したいときは
propagate = 1
と設定します。
3.設定ファイルを書くときの注意
実際に私が設定ファイルを書いているときに嵌ったことをいくつかあげておきます。
1. 設定ファイルには必ず "root" ロガーの設定を行う
最初から設定が行われている "root" ロガー。設定ファイルにまで書かなくてもいいだろう、その分減って見やすくなるし。
...そう思い、 "root" ロガーの設定を行わずに設定ファイルを書き、loggingの実験を行いました。
そのときの私は、まさかそんなことで2時間も悩むことになるとは思いもしませんでした。
2.args=(sys.stdout,) の ',' を忘れない
インタープリタ上では
StreamHandler(sys.stdout)
で動きますが、設定ファイルに書き込む際には(sys.stdout,)としなければ
エラーになってしまいます。
タプルになるように書かないといけないのではないかと思います。
実はライブラリリファレンスに書いてあることばかりだったりします。
やっぱり困ったときは基本に立ち返ることも重要ですね。
4.おまけ
設定ファイルのひな形
面倒なrootロガーの設定を済ませたものを載せておきます。
DEBUGレベル以上のログを画面に出力する設定になっています。
これに、使いたいロガーの設定を付け足していけば設定ファイルが出来上がります。
[loggers]
keys=root
[formatters]
keys=default
[handlers]
keys=default
[formatter_default]
format=%(asctime)s %(name)s %(levelname)s %(message)s
datefmt=
[handler_default]
class=StreamHandler
formatter=default
args=(sys.stdout,)
[logger_root]
level=DEBUG
handlers=default
Leave a comment