【Python】logging の設定ファイル


はじめに

python を使うおじさんですが、未だにlogging の使い方がこなれていない。
おじさんは

  1. モジュールとそれを呼び出すモジュールとで、両方に logger を設定して使いたい
  2. 出力の設定はまとめておきたい

をしたいのだが、できていません。今回、設定をファイルから読み込むことで、少し進展しそうです。ので、メモ。

Configuration file を読む

設定ファイルは、logging.config.dictConfig() で読むことができます。

動作例

同じディレクトリに設定ファイルを置いてあります。

.
├── logging.yaml
└── main.py

設定ファイル

まず、設定ファイルの方です。最初は、最後の行にある disable_existing_loggers: False が無くて動きませんでした。大事です。

logging.yaml
version: 1
formatters:
  simple_fmt:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: INFO
    formatter: simple_fmt
    stream: ext://sys.stdout
  console_AAA:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple_fmt
    stream: ext://sys.stdout
loggers:
  AAA:
    level: DEBUG
    handlers: [console_AAA]
    propagate: no
root:
  level: DEBUG
  handlers: [console]
disable_existing_loggers: False

当然ながら、yamlファイルがきちんと書かれちないとload するときにエラーが出ます。class AAA では debug level で出力するようにしています。dictConfig() に渡される辞書については、下記に書かれています。version, formatters, handlers などのキーが必要です。

動作例

以下のプログラムを動かしてみます。

main.py
from logging import getLogger,config
import yaml

logger = getLogger(__name__)

class AAA(object):
    def __init__(self):
        self.logger = getLogger(self.__class__.__name__)
        self.logger.debug("class name is {}".format(self.__class__.__name__))
    def do_something(self):
        self.logger.info("doing something")

def main():
    aaa = AAA()
    aaa.do_something()

    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')

if __name__ == "__main__":
    config.dictConfig( yaml.load(open("logging1.yaml").read(), Loader=yaml.SafeLoader) )
    main()

動かすと、class AAA にある logger では debug levelで出力されますが、main() なかでは info レベルです。

$ python main_yaml.py
2021-05-11 21:41:16,663 - AAA - DEBUG - class name is AAA
2021-05-11 21:41:16,663 - AAA - INFO - doing something
2021-05-11 21:41:16,664 - __main__ - INFO - info message
2021-05-11 21:41:16,664 - __main__ - WARNING - warn message
2021-05-11 21:41:16,664 - __main__ - ERROR - error message
2021-05-11 21:41:16,664 - __main__ - CRITICAL - critical message

まとめ

とりあえず動いた。もう少し調べてもよいかなと思うのは、

  • Formatter の使いこなし。。。
  • 設定ファイルの書き方。Loggerのドキュメントに書かれていますが、json や独自形式?の .conf でも読むことができるようです。 https://docs.python.org/ja/3/howto/logging.html
  • 別ファイルにあるlogger を出力する(本当はこれを確認したい)

(2021/05/11)