1
1

Pythonで動かしっぱなしのプログラムのログを毎日違うファイルに保存したい

Last updated at Posted at 2024-08-28

きっかけ

とあるプログラムを延々と動かしてたんです。1週間ほど。
ログを出していたのですが、動かしっぱなしなので一つのログファイルにログを溜め込み・・・。(ちょっと怖い)

いや、これメモリーを圧迫したりとかしないの?(コンピューターは(も)よく知らない)

とういうことで、「動かしっぱなしのプログラムのログファイルを日毎に取得したい」って思いました。
精神的にも安心できそうだしね。




環境

2020 M1 MacBookAir
Python==3.10.8




ドキュメントを読んでみた

ム・ズ・カ・シ・イ
それっぽいのも見当たらない




GPTに聞いてみた

:relaxed::relaxed::relaxed:さすが!!!

とあるクラスを紹介してくれました。そして使ってみたらバッチリ。
だから紹介します!キリッ!





そのクラスとは
TimedRotatingFileHandler!!!





たいむどろーていてぃんぐふぁいるはんどら
時間設定されたくるくる回るファイルを取り扱うやつ


そんな感じ(意訳が過ぎるだろ)

ということで、ドキュメントを索引から探す・・・見つからん
見つけられないのでクラス名でサイト内検索したらあった!喜




さっき見た索引をよく見ると
索引.png

横の+をクリックして開いたらlogging.handlersがあった。ここか!




実装例

import logging
from logging.handlers import TimedRotatingFileHandler
import time

log_file_path = './log/my_watchdog.log'

formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')
logger = logging.getLogger(__name__)
handler = TimedRotatingFileHandler(
    filename=log_file_path,    # ログファイルのパス
    when='M',                  # ファイルを作る時間単位。この場合は分。
    interval=1,                # 1分ごとにログファイルを新たに作成
    backupCount=7,             # 過去7つのログファイルを保存
    encoding='utf-8',          # エンコーディングをUTF-8に設定
    delay=False,               # ちょっと謎
    # utc=False                  # ローカルタイムでローテーション(時間設定にした場合)
    )

handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler) # ここで色々な設定を入れたハンドラーをloggerに設定


logger.info('**************** start ***************')

while True:
    # 処理
    logger.info('処理中')
    time.sleep(20)  # サンプルとして20秒毎にログを記録



動作結果

うん、目的達成できそう。



まずは1分経過後にできた最初のファイル最初のファイル
スクリーンショット 2024-08-28 22.46.04.png

スタートの時だけ1行付け加えているのでわかりやすいですね。
**************** start ***************

指定したファイル名の後ろに2024-08-28_22-40と日付と時間が付与されてます。




この時、書き込まれているファイルの名前はは指定した通りで、my_watchdog.logです。
スクリーンショット 2024-08-28 22.48.57.png




と、ここまで書いていたら最初のファイルが消えてました。
スクリーンショット 2024-08-28 22.50.55.png
上に記した最初のファイルmy_watchdog.log.2024-08_22−40が無いです。
そして末尾が−42までのファイルが消えてます。




今回は上の通り、毎分新しいログファイルを作り、過去7ファイルを保持するということが達成できました。
常時起動のプログラムで膨大な行数になりそうなログファイルになりそうな時はうまく時間設定、ファイル数設定をしてメモリーやらストレージをうまく使えそうです。




TimedRotatingFileHandler解説

filename:

ログファイルのパスを指定します。
例: './log/my_watchdog.log'
そういや、連続稼働しているプログラムの名前がバレそうだ。www



when:

ログファイルをどんな周期で作成するか、指定するための時間単位を指定します。
主要なオプション:
'S': 秒ごと
'M': 分ごと
'H': 時ごと
'D': 日ごと
'midnight': 日付が変わるとき
'W': 曜日ごと(デフォルトは月曜日)

今回は検証なので、M:分を使いました。(秒とか目で追うだけで精一杯になっちまう。)



interval:

ログファイルを生成し直す間隔を指定します。whenで指定した単位に対する数値です。
今回は1を設定したので、whenの設定で単位をとしたので1分毎にログファイルを生成します。

backupCount:

古いログファイルをいくつ保存するかを指定します。
今回は7を指定したので、7つのファイルを保持することになります。
これで、when='D'とすると日毎の1週間分のファイルが保持できます。



encoding:

ログファイルのエンコーディングを指定します。
まぁ、utf-8でええんちゃう?w



delay:

delay が true なら、ファイルを開くのは emit() の最初の呼び出しまで延期されます。と書いてあるけど、正直よくわからない。ということで、GPTに聞くとこう返してくれた。

Trueに設定すると、実際にログファイルが書き込みされるまでファイルを開かないようにします。
ま、特に設定はいらんかな(知らんけど)



utc:

Trueに設定すると、ローテーションの時間をUTC(協定世界時)で計算します。
ま、時間設定する時には必須ですね。
日付変更に設定したいのに、9時間ズレたとかやらかしそう。www
基本はFalseでいいでしょう。




atTime

ここにdatetime.timeで時刻を渡してあげるとこの時間で更新されるらしい(未確認)
マニュアルにはdatetime.timeインスタンスじゃないといけないって明示されてました。
ここにハンドラだけ書いておく。(自分用)

from logging.handlers import TimedRotatingFileHandler
from datetime.datetime import time

handler = TimeRotatingFileHandler(
    filename='./log/my_watchdog.log',
    atTime=time(8, 30),
    utc=False,
    )
    



おわりに

GPTさんの手を借りながらなんとか目的を果たすことができました。
監視系のソフトや、1週間ほど動きっぱなしの現場系ソフトを作ったことがあります。
ちょっと気になっていた、一つのログファイルが大きくなりすぎる問題がこれで解決できそうです。
あ、今んとこ問題は出てないけどね。(知らんけど)

じゃ、また!

1
1
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
1
1