【python】logging.Loggerを使ってファイルと標準出力の両方にログを出力する
「運用始まった後のログはファイルに出したいけど、開発やデバッグ中のログはコンソールに出したいじゃん」を叶えます。
Loggerを使ったログ出力の導入についてはこちらの記事で。
結論
ハンドラ複数作ってroot_logger.addHandler()複数回使えば複数のハンドラを登録できます。
以上。
もうちょっと詳細を…
from logging import getLogger, StreamHandler ,handlers, Formatter, DEBUG, INFO
from pathlib import Path
import sys
def set_logger(file_path):
# ルートロガーを召喚して全体にかかわる設定をする
root_logger = getLogger()
root_logger.setLevel(DEBUG)
# ファイルに出力するためのハンドラの設定をして、addHandler()する
rotating_handler = __create_rotating_handeler(file_path)
root_logger.addHandler(rotating_handler)
# ストリームに出力するためのハンドラの設定をして、addHandler()する
stream_handler = StreamHandler(sys.stdout)
stream_handler.setLevel(DEBUG)
root_logger.addHandler(stream_handler)
# ここから下は可読性を保つために切り出した細かい処理
# 細かい設定をして、rotating_handlerを作る
def __create_rotating_handeler(file_path):
# ファイルが存在しなかったら作成する
__prepare_log_file(file_path)
rotating_handler = handlers.RotatingFileHandler(
file_path,
mode="a",
maxBytes=100 * 1024,
backupCount=3,
encoding="utf-8"
)
log_format = Formatter('%(asctime)s : %(levelname)s : %(filename)s - %(message)s')
rotating_handler.setFormatter(log_format)
rotating_handler.setLevel(INFO)
return rotating_handler
# ファイルが存在しなかったら作成する
def __prepare_log_file(file_path):
file_path_obj = Path(file_path)
if not file_path_obj.parent.exists():
file_path_obj.parent.mkdir()
if not file_path_obj.exists():
file_path_obj.touch()
前回の記事で作成したrotating_handlerの作成部分を関数として切り出し、さらに外部から引数でファイルパスを受け取れるようにしました。
そして、ログファイルやフォルダがなければ作るようにしてあります。これで、gitの管理からログフォルダ外してたら本番環境にフォルダ作ってなくて落ちるみたいなあほなことを避けられます。
さらに、ストリームに出力するためのハンドラの設定
stream_handler = StreamHandler(sys.stdout)
stream_handler.setLevel(DEBUG)
root_logger.addHandler(stream_handler)
を加えるだけで完成です。
ストリーム用のハンドラはレベルをDEBUGに、ファイル出力用のハンドラのレベルはINFOにしておくことで、デバッグ用の詳細なログはコンソールで実行したときのみに、あとから確認したい重要なログはファイルに残るようになります。
もちろん、ハンドラに設定するレベルを変えれば、必要に応じてファイルには些末なものも全部残しておく、コンソールには肝心なところだけ出す、というような運用もできます。
これ以上詳しい設定をいろいろしたくなってきたら、さすがに設定ファイルの外出しを検討かなーと思っているところです。
この記事が気に入ったらサポートをしてみませんか?