0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonのloggingのログ出力先ファイルを動的に変更する

Posted at

やりたいこと

ログの出力先を年月日ごとに動的に変更する。

TimedRotatingFileHandlerを使用すれば似たようなことはできますが、今回はローテーションではなく出力先を動的に変更します。

LOG_DIR
├── 2025
│   ├── 01
│   │   ├── LOG_FILE.20250101.log
│   │   ├── ...
│   │   └── LOG_FILE.20250131.log
│   └── 02
│       ├── LOG_FILE.20250201.log
│       ├── ...
│       └── LOG_FILE.20250228.log <- このファイルを直接つくる
└── LOG_FILE <- このファイルはつくらない

TimedRotatingFileHandlerを使った実装は以下の記事を参照ください。

実装

FileHandlerから継承します。
書き込みのたびに、日時を取得してファイルを開きなおす必要があるので、TimedRotatingFileHandlerを利用するほうが賢明だとは思います。:cry:

サンプルコード
import time
from datetime import datetime
from logging import FileHandler, getLogger
from pathlib import Path
from zoneinfo import ZoneInfo


class MyFileHandler(FileHandler):
    def __init__(
        self,
        filename,
        mode="a",
        encoding=None,
        delay=False,
        errors=None,
    ):
        self.org_baseFilename = None  # Noneで初期化する
        super().__init__(filename, mode, encoding, delay, errors)

    def _open(self):
        # self.baseFilenameの初期値を覚えておく
        if not self.org_baseFilename:
            self.org_baseFilename = self.baseFilename
        # filenameを取得する
        self.baseFilename = self.namer(self.org_baseFilename)
        # ディレクトリが存在しない場合は作成する
        Path(self.baseFilename).parent.mkdir(parents=True, exist_ok=True)
        return super()._open()

    def namer(self, filename):
        # 現在日時を取得する
        now = datetime.now(ZoneInfo("Asia/Tokyo"))
        year, month, day = now.strftime("%Y"), now.strftime("%m"), now.strftime("%d")
        # filenameに現在日時を追加する
        filepath = Path(filename)
        filepath_with_date = (
            filepath.parent / year / month / f"{filepath.name}_{year}{month}{day}"
        )
        # FIXME: **** **** ここから動作確認用コード(不要なら消す) **** ****
        filepath_with_date = (
            filepath_with_date.parent
            / f"{filepath_with_date.name}{now.strftime('%H%M%S')}"
        )
        # FIXME: **** **** ここまで動作確認用コード(不要なら消す) **** ****
        return str(filepath_with_date)

    def emit(self, record):
        self.close()  # 毎回開き直す
        return super().emit(record)


# ログを出力してみる
logger = getLogger("logger")
logger.addHandler(MyFileHandler("LOG_FILE_NAME"))
for i in range(20):
    logger.error(f"ERROR MESSAGE{i}")
    time.sleep(0.2)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?