Python logging 使い方


Pythonのloggingについてどこよりも簡潔に有用な解説をします。

Python - logging 公式ドキュメント

loggingメインプログラム

appLogger.py
import os
import time
import threading
import logging
import logging.handlers

_logger = None

def initLogging(isPrinted: bool):
    """ロギングの初期設定
    (ログは指定したフォルダに保管される)

    Args:
        isPrinted (bool): コンソール画面に表示するときTrue
    """    """
    ロギング設定
    """    
    global _logger

    _logger = logging.getLogger('App')
    _logger.setLevel(logging.INFO)

    ''' ログファイル保存用のディレクトリ '''
    if os.path.exists('./log') == False:
        os.makedirs('./log')

    ''' ログをファイルに出力するための設定 '''
    rfh = logging.handlers.RotatingFileHandler(
        filename='./log/App.log',
        maxBytes=1024*1024,
        backupCount=5
    )

    _logger.addHandler(rfh)
    formatter = logging.Formatter('%(asctime)s,%(name)s,%(threadName)s,%(lineno)d,%(levelname)s,%(message)s')
    rfh.setFormatter(formatter)

    ''' ログをコンソールに出力するための設定 '''
    if isPrinted:
        handler = logging.StreamHandler()
        handler.setLevel(logging.INFO)
        _logger.addHandler(handler)
        handler.setFormatter(formatter)

    _logger.info('initLogging fin.')

def func1():
    """Thread 1 Mehotd
    """    
    while True:
        _logger.info("Thread1: Heartbeat...")
        time.sleep(1)

def func2():
    """Thread 2 Mehotd
    """    
    while True:
        _logger.info("Thread2: Heartbeat...")
        time.sleep(1)

if __name__ == '__main__':

    ''' ロギング設定の初期化 '''
    initLogging(True)

    ''' ロギング出力テスト '''
    _logger.info("INFO")
    _logger.warning("WARNING")
    _logger.error("ERROR")
    _logger.critical("CRITICAL")

    ''' 読み込み用スレッド '''
    thread1 = threading.Thread(target=func1)
    thread1.start()

    ''' 書き込み用スレッド '''
    thread2 = threading.Thread(target=func2)
    thread2.start()

簡単にプログラムの解説をします。

RotatingFileHandler

ログファイルの出力と世代管理をします。上記の場合、logフォルダにApp.logというログファイルが生成されます。

filename 出力ファイル名
maxBytes 1ファイルの最大サイズ
backupCount 世代管理数

maxBytesを超えると自動的に「App.log」 -> 「App.log1」 に変換され、以降のログは「App.log」に保存されます
上記の場合、世代管理は5なので、「App.log5」まで行くと古いものから削除されます。

出力形式は Formatter() で設定が可能です。

StreamHandler

ここではコンソール画面への出力設定をします。出力内容は上記と同じになります。


getChild()による子ロガー作成

loggingメインプログラムで作成したLogging設定を使って、子ロガーを作成します。

これはPythonプログラムが複数に渡るときに便利です。

以下サンプルプログラムになります。親プログラムは上記とほぼ同じです。

LoggerParent.py
''' ---------------------------
    Python Logging Parent
---------------------------'''
import os
import logging
import logging.handlers

_logger = None

def initLogging(isPrinted: bool):
    """ロギングの初期設定
    (ログは指定したフォルダに保管される)

    Args:
        isPrinted (bool): コンソール画面に表示するときTrue
    """    """
    ロギング設定
    """    
    global _logger

    _logger = logging.getLogger('App')
    _logger.setLevel(logging.INFO)

    ''' ログファイル保存用のディレクトリ '''
    if os.path.exists('./log') == False:
        os.makedirs('./log')

    ''' ログをファイルに出力するための設定 '''
    rfh = logging.handlers.RotatingFileHandler(
        filename='./log/App.log',
        maxBytes=1024*1024,
        backupCount=1
    )

    _logger.addHandler(rfh)
    formatter = logging.Formatter('%(asctime)s,%(name)s,%(threadName)s,%(lineno)d,%(levelname)s,%(message)s')
    rfh.setFormatter(formatter)

    ''' ログをコンソールに出力するための設定 '''
    if isPrinted:
        handler = logging.StreamHandler()
        handler.setLevel(logging.INFO)
        _logger.addHandler(handler)
        handler.setFormatter(formatter)

    _logger.info('initLogging fin.')

if __name__ == '__main__':

    ''' ロギング設定の初期化 '''
    initLogging(True)

    ''' ロギング出力テスト '''
    _logger.info("INFO")
    _logger.warning("WARNING")
    _logger.error("ERROR")
    _logger.critical("CRITICAL")

    ''' Childアプリの起動 '''
    import LoggerChild
    LoggerChild.Start()

続いて、子ロガー側の紹介です。
実はたった1行で子ロガーは親ロガーの設定を引き継いで作成できます。

LoggerChild.py
''' ---------------------------
    Python Logging Child
---------------------------'''
import logging

def Start():

    ''' 子ロガーの設定 '''
    _logger = logging.getLogger("App").getChild("Child")
    _logger.info("logging child fin.")

Parent側を実行したときの結果です。
出力結果は以下となります。子ロガーの方は、nameが「App.Child」になります。

以上でloggingの解説は終了します。
※実務で利用する場合は、適宜例外処理などは追加してください。