[Python] ログレベルでログの出力先を標準出力、標準エラー出力に分ける

概要

Pythonでプログラムを書いているときに、ログ収集プラットフォームに送るログの出力先をログレベルで標準出力、標準エラー出力に分けたいことがあったので、loggingモジュールのフィルタオブジェクトを使って実装する方法を記載します。

この記事で紹介している方法では、それぞれのログレベルの出力先は以下になります。

ログレベル出力先
CRITICAL標準エラー出力
ERROR標準エラー出力
WARNING標準エラー出力
INFO標準出力
DEBUG標準出力

実装

Pythonのloggingモジュールではログレベルを指定することで、指定したレベル以上のレベルのログを出力することができます。

INFOやDEBUGのログレベルを指定すると、よりレベルの高いWARNING, ERROR, CRITICALのログも出力されてしまうので、フィルタを設定して不要なログを除外します。

ソースコード (main.py)
import logging import sys def set_logger(name=None): # INFO以下のログを標準出力する stdout_handler = logging.StreamHandler(stream=sys.stdout) stdout_handler.setLevel(logging.DEBUG) stdout_handler.addFilter(lambda record: record.levelno <= logging.INFO) # WARNING以上のログを標準エラー出力する stderr_handler = logging.StreamHandler(stream=sys.stderr) stderr_handler.setLevel(logging.WARNING) # ロガーにハンドラを設定する logger = logging.getLogger(name) logger.setLevel(logging.DEBUG) logger.addHandler(stdout_handler) logger.addHandler(stderr_handler) def main(): set_logger() logger = logging.getLogger() logger.debug('This is a debug log.') logger.info('This is a info log.') logger.warning('This is a warning log.') logger.error('This is a error log.') logger.critical('This is a critical log.') if __name__ == '__main__': main()

動作確認

動作確認
# DEBUG, INFOログが標準出力に書き込まれている $ python3 main.py 2> /dev/null This is a debug log. This is a info log. # WARNING, ERROR, CRITICALログが標準エラー出力に書き込まれている $ python3 main.py > /dev/null This is a warning log. This is a error log. This is a critical log.

コメントする