Pythonの標準モジュール「logging」で画面とファイル両方にログ出力する方法
はじめに
Pythonには「logging」という、ログ出力のための標準モジュールがあることを知ったので使ってみました。
(ログをprintで画面出力、open→writeでファイル出力するよりは便利です。)
また、「logging」のデフォルト設定ではログを画面に出力するのみなので、
画面とファイル両方に同時出力する方法を調べてみました。
loggingについて
「logging」のマニュアルは以下となります。
docs.python.org
loggingの動作確認
loggingでどんなことができるのか確認してみました。
デフォルト設定でのログ出力
import logging logging.critical("This is Critical.") logging.error("This is Error.") logging.warning("This is Warning.") logging.info("This is Info.") logging.debug("This is Debug.")
<実行結果>
デフォルト設定ではログレベルのWarning以上が画面に出力されます。
rootは「root階層にあるロガー」を意味しています。
CRITICAL:root:This is Critical. ERROR:root:This is Error. WARNING:root:This is Warning.
ファイルへの出力
Debug以上のログをファイル出力する例となります。
basicConfigメソッドは基本的な環境設定を行うメソッドです。
basicConfigメソッドで設定できる項目は他のメソッド(setLevelなど)でも設定可能です。
import logging logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)
ログフォーマットの設定
ログフォーマットはbasicConfigメソッドの引数「format」で設定します。
setFormatterメソッドでも設定できます。
import logging logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s') logging.warning('is when this event was logged.')
<実行結果>
2022-08-22 01:10:49,044:WARNING:is when this event was logged.
ログローテート
「RotatingFileHandler」はファイルサイズ、「TimedRotatingFileHandler」は時間でログローテートできます。
import logging import logging.handlers rh = logging.handlers.RotatingFileHandler(filename="test.log", maxBytes=1000, backupCount=3) formatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s") rh.setFormatter(formatter) logger = logging.getLogger() logger.addHandler(rh) while True: logger.warning("This is Warning.")
<実行結果>
上記例だと、1000バイトでローテートされ、現在のログ含め4世代残ります。
> ls test.log* Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2022/03/01 23:21 0 test.log -a---- 2022/03/01 23:21 990 test.log.1 -a---- 2022/03/01 23:21 990 test.log.2 -a---- 2022/03/01 23:21 990 test.log.3
画面とファイル両方にログ出力
下記条件で、画面とファイル両方にログ出力する例です。
流れとしては、まずgetLoggerでrootロガーを取得し、ログレベルを設定します。
その後、画面出力用(StreamHandler)とファイル出力用(FileHandler)のそれぞれのハンドラーを作成し、ログフォーマットを設定の上、ロガーに追加します。
import logging # ロガーの取得、ログレベル設定 logger = logging.getLogger() logger.setLevel(logging.INFO) # ログフォーマット logFormatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s') # 画面出力設定 consoleHandler = logging.StreamHandler() consoleHandler.setFormatter(logFormatter) logger.addHandler(consoleHandler) # ファイル出力設定 fileHandler = logging.FileHandler("test.log", mode="a", encoding="utf_8") fileHandler.setFormatter(logFormatter) logger.addHandler(fileHandler) # ログ出力 logger.info("This is info")