2016-05-22 18:02:48,092 INFO [message]
2016-05-22 18:02:48,199 INFO [message]
2016-05-22 18:02:48,300 INFO [message]
...
のように出力時刻、レベル名、メッセージをログファイルに出力する場合を考える。
また、一定時間ごとにロテートする機能が欲しいとする。
実装1
import logging import time from logging.handlers import TimedRotatingFileHandler logger = logging.getLogger("app") logger.setLevel(logging.INFO) handler = TimedRotatingFileHandler('test.log', when="s", interval=1, backupCount=5) handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) logger.addHandler(handler) def main(): for i in range(100): logger.info("%d th iteration!" % i) time.sleep(0.1) if __name__ == '__main__': main()
TimedRotatingFileHandlerを使うと目的のロテートが出来る。
上の実装だと1sごと(when, intervalで設定)にロテートするようにしている。
最新のログはtest.logに吐かれ、古いログは
test.log.2016-05-22_18-02-48
test.log.2016-05-22_18-02-49
...
のようにロテートされる。保持する古いログファイルは5つ(backupCountで設定)までとしている。
実装2
複数のロガーを使いたい場合は、実装1のように毎回プログラム上でロガーを作成していては面倒。その場合は、設定ファイルを使ってロガーを定義しておくとよい。
log_conf = { "version": 1, "disable_existing_loggers": False, "formatters": { "simple": { "format": "%(asctime)s %(levelname)s %(message)s" } }, "handlers": { "time_rotate": { "class": "logging.handlers.TimedRotatingFileHandler", "formatter": "simple", "filename": "test.log", "when": "s", "interval": 1, "backupCount": 5 } }, "loggers": { "app": { "level": "INFO", "handlers": ["time_rotate"] } } }
とりあえずpythonのdictで設定を書いた。
設定ファイルはdictに変換できればいいので、jsonやyamlで書いてもいい。
設定ファイル3行目のdisable_existing_loggersは、既存のロガーを無効化するかどうかの設定。デフォルト の値はTrueで、その場合、設定ファイルをロードする前に生成されたロガーが無効化されてしまう。無効化して欲しくない場合は、Falseを設定する。
設定ファイルのロードは以下のように行う。実装1と比べるとだいぶスッキリした。
import logging.config import time from conf import log_conf logging.config.dictConfig(log_conf) logger = logging.getLogger("app") def main(): for i in range(100): logger.info("%d th iteration!" % i) time.sleep(0.1) if __name__ == '__main__': main()