logging

【Python】loggingのRotatingFileHandlerを使って指定ファイルサイズでログローテーションする方法

【Python】loggingのRotatingFileHandlerを使って指定ファイルサイズでログローテーションする方法

Pythonのloggingモジュールで、RotatingFileHandlerを使って指定ファイルサイズでログローテーションする方法を解説します。

指定ファイルサイズでログローテーション

Pythonに限らずですがプログラムの開発をした際にはログ出力し、障害時の際には状況を把握できるようにすることが非常に重要です。

業務アプリケーションといった常時動作しているシステムの場合、ログファイルが常に出力されるのでログファイルが肥大化し、ディスクの容量を圧迫してしまいシステム全体の動作に影響を与える可能性があります。

その場合には、ログローテーションすることで回避します。例えば「ログデータの総量が一定の容量を超えたら別のファイルにログを出力する」「一定時間が過ぎたら別のファイルにログを出力する」といったように切り替えます。

pythonではロギングのモジュールとしてloggingが用意されています。loggingにはハンドラというものがありますが、RotatingFileHandlerを使用することで指定したファイルサイズによってログローテーションを実現することができます。

本記事では、RotatingFileHandlerの使用方法について紹介します。

指定時間でログローテーションする方法としては「loggingのTimedRotatingFileHandlerを使って指定時間でログローテーションする方法」でまとめていますので興味があれば参考にしてください。

loggingのRotatingFileHandlerでログローテーションする方法

Pythonでログ出力に使用されるloggingでRotatingFileHandlerによってログローテーションする方法を説明します。

RotatingFileHandlerの使い方

loggingで指定ファイルサイズによるログローテーションをする場合は、以下のようにRotatingFileHandlerを設定して使用します。

import logging.handlers
import time


def main():
    # ロギングの基本設定
    formatter = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
    logging.basicConfig(level=logging.INFO, format=formatter, encoding="utf_8")

    # ロガーの作成
    logger = logging.getLogger(__name__)

    # ログレベルをDEBUGへ変更
    logger.setLevel(logging.DEBUG)

    # ログローテーションのハンドラーを設定
    #   maxBytes: 1ログファイルの上限サイズ(byte単位)
    #   backupCount: バックアップとして保持するログファイル数
    h = logging.handlers.RotatingFileHandler("test.log", maxBytes=10000, backupCount=5)

    # フォーマットを設定
    h.setFormatter(logging.Formatter(formatter))

    # ロガーにハンドラーを設定
    logger.addHandler(h)
    
    for _ in range(1000):
        time.sleep(0.1)
        logger.debug("log rotation test")


if __name__ == "__main__":
    main()

【実行結果例】対象フォルダをdirコマンドで確認した例

logging RotatingFileHandler

【詳細説明】

以降でプログラムの各部分について解説をします。

まず、RotatingFileHandlerを使用する場合には「logging.handlers」をimportする必要があります。

import logging.handlers

以下の部分は、ログ基本設定の部分でメインプログラムなどで設定する基本的な設定内容です。

    # ロギングの基本設定
    formatter = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
    logging.basicConfig(level=logging.INFO, format=formatter, encoding="utf_8")

ロガーを作成し、ログローテーションのためのRotatingFileHandlerを設定しているのは以下の部分になっています。

    # ロガーの作成
    logger = logging.getLogger(__name__)

    # ログレベルをDEBUGへ変更
    logger.setLevel(logging.DEBUG)

    # ログローテーションのハンドラーを設定
    #   maxBytes: 1ログファイルの上限サイズ(byte単位)
    #   backupCount: バックアップとして保持するログファイル数
    h = logging.handlers.RotatingFileHandler("test.log", maxBytes=10000, backupCount=5)

    # フォーマットを設定
    h.setFormatter(logging.Formatter(formatter))

    # ロガーにハンドラーを設定
    logger.addHandler(h)

ログローテーションのハンドラーを作成する際には、「ファイル名」、「maxBytes」、「backupCount」といった引数を指定します。maxBytesは上限とするファイルサイズをバイトで指定します。backupCountについては、いくつの古いログファイルを保持するかを指定します。

上記の例ではtest.logというファイルにログを出力し、10KBを上限に5つのバックアップファイルでローテーションするという設定です。

また、フォーマットを指定しておかないと入力した文字列のみ出力されてしまうので、setFormatterでハンドラにフォーマットを指定しています。最後にaddHandlerでロガーにハンドラーを設定しています。

上記まででログローテーションの準備は完了です。以下の部分ではログ出力の確認をしています。sleepで一定時間止まってからログを出力するようにしていますので、繰り返し回数やsleep時間などは任意に変えてみてください。

    for _ in range(1000):
        time.sleep(0.1)
        logger.debug("log rotation test")

複数回実行いただくと、test.logに常に最新のログが出力されることが分かります。

ログファイルは、指定したサイズに達するとtest.log.1、test.log.2、…、test.log.5というようにファイルがローテーションされて出力されます。test.log.1の方が新しいログで、5に進むにつれて古いログになります。つまりローテーションのタイミングでファイルがリネームされているわけです。

以上が、RotatingFileHandlerを使ってファイルサイズ指定によるログローテーションをする方法でした。

Note

RotatingFileHandlerの公式ドキュメントページはこちらを参考にしてください。