概要
Pythonでプログラムを書いているときに、ログ収集プラットフォームに送るログの出力先をログレベルで標準出力、標準エラー出力に分けたいことがあったので、loggingモジュールのフィルタオブジェクトを使って実装する方法を記載します。
この記事で紹介している方法では、それぞれのログレベルの出力先は以下になります。
ログレベル | 出力先 |
---|---|
CRITICAL | 標準エラー出力 |
ERROR | 標準エラー出力 |
WARNING | 標準エラー出力 |
INFO | 標準出力 |
DEBUG | 標準出力 |
実装
Pythonのloggingモジュールではログレベルを指定することで、指定したレベル以上のレベルのログを出力することができます。
INFOやDEBUGのログレベルを指定すると、よりレベルの高いWARNING, ERROR, CRITICALのログも出力されてしまうので、フィルタを設定して不要なログを除外します。
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.