Raspberry Pi & Python 開発ブログ ☆彡

Raspberry PiとPythonの基本的な使い方をわかりやすく解説。初心者、入門者必見!!

Pythonでログ出力:loggingモジュールの使い方

今回はloggingモジュールを使用して、ログを出力する方法を紹介したいと思います。ログの出力方法や形式等を設定できるので、便利です。それでは説明してきます。

loggingモジュールの基本

基本がとても大事です。大きく分けて3つです。

名前を付けて、loggingインスタンスを生成する

名前を決めて、loggingインスタンスを生成します。名前で区別することができ、名前ごとに出力形式やログレベル等を設定することができます。何も名前を付けない場合はrootという名前が割り当てられます。

import logging

logger = logging.getLogger() # 引数に何も指定しないとrootという名前になる
print(logger.name)
>> root

logger = logging.getLogger('test') # 引数で指定したtestという名前になる
print(logger.name)
>> test

handlerを設定する

ログの出力形式を決めて、handlerに設定します。出力形式はいろいろありますが、主に使うものを記載しておきます。

・StreamHandler(コンソールへログ出力)
・FileHandler(ファイルへログ出力)
・RotatingFileHandler(ファイルへ出力、容量によりローテーションする)
・TimedRotatingFileHandler(ファイルへ出力、時間によりローテーションする)

handler = logging.StreamHandler() # コンソール出力するハンドラー
handler = logging.FileHandler(filename='log.txt') # ファイル出力するハンドラー

#ファイルへ出力、容量でローテーションするハンドラー
handler = logging.handlers.RotatingFileHandler(
    filename='log.txt', # ログファイル名
    maxBytes=100000 # ローテションする容量
    backupCount=3 # ローテーションするファイル数
)

#ファイルへ出力、時刻でローテーションするハンドラー
handler = logging.handlers.TimedRotatingFileHandler(
    filename='log.txt', # ログファイル名
    when='midnight', # ローテーションする時間 
    backupCount=3 # ローテーションするファイル数
)

# ログの出力レベルを設定 DEBUG,INFO,WARINIG,ERROR,CRITICAL
handler.setLevel(logging.DEBUG)

handlerの設定の詳細については、下記ページを参考にしてください。
https://docs.python.org/ja/3/library/logging.handlers.html

出力のフォーマットを決める

ログの出力フォーマットを決めます。

# 出力フォーマット:時間 - ログレベル - ログメッセージ 
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

# 出力フォーマット:時間 - ロガーの名前 - スレッドID - ソースの行番号 - ログメッセージ 
formatter = logging.Formatter('%(asctime)s - %(name)s - %(threadName)s - L%(lineno)s - %(message)s')

フォーマットで指定できるパラメータの詳細については、下記ページを参考にしてください。
https://docs.python.org/ja/3/library/logging.html#logging.Formatter

上記3つの設定でロガーを作る

logger = logging.getLogger('test') # 名前を付けてインスタンスを生成
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # フォーマットを定義
handler = logging.StreamHandler() # コンソール出力するハンドラーを生成
handler.setLevel(logging.INFO) # ログレベルの設定
handler.setFormatter(formatter) # フォーマットを設定
logger.addHandler(handler) # testロガーにハンドラを登録する

logger.error("エラーメッセージ")

これで、logger(testという名前)は、上記フォーマットでコンソールにログ出力します。 logging basic

Configファイル作成する

ロガーは出力形式やフォーマット等、設定する項目が多いので、Configファイルで設定ができるようになっています。Configファイルを作ったほうが、わかりやすくまとめることができますので、Configファイルを作ることをお勧めします。上記の基本がわかっていれば、難しくありません。

import logging
import logging.config

_config = {
    'version': 1, # バージョン管理、現状1しかない
    'formatters': { # フォーマットを2つ作成
        'short': {
            'format': '%(asctime)s - %(levelname)s - %(message)s'
        },
        'long': {
            'format': '%(asctime)s - %(name)s - %(threadName)s - L%(lineno)s - %(message)s'
        }
    },
    'handlers': { # ハンドラーを2つ作成
        'consoleHandler': {
            'level': 'DEBUG',
            'formatter': 'long',
            'class': 'logging.StreamHandler',
        },
        'rotatingfileHandler': {
            'level': 'DEBUG',
            'formatter': 'short',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'log.txt',
            'maxBytes': 1000000,
            'backupCount': 3,
        }
    },
    'loggers': {
        'test1': { # 名前が:test1のロガー設定
            'handlers': ['consoleHandler'],
            "propagate": False, # この設定をしないとtest1ロガーのログとrootロガーのログが出力されてしまう
            'level': "DEBUG"
        },
        'test2': { # 名前が:test2のロガー設定
            'handlers': ['rotatingfileHandler'],
            "propagate": False, # この設定をしないとtest2ロガーのログとrootロガーのログが出力されてしまう
            'level': "DEBUG"
        }
    },
    'root': { # 名前が:rootのロガー設定
            'handlers': ['consoleHandler', 'rotatingfileHandler'],
            'level': "DEBUG"
    }
}

logging.config.dictConfig(_config) # Configファイルの読み込み

logger_root = logging.getLogger()
logger_root.debug('logtest_root')
logger_test1 = logging.getLogger('test1')
logger_test1.debug('logtest_test1')
logger_test2 = logging.getLogger('test2')
logger_test2.debug('logtest_test2')

下記が実行結果となります。rootロガーはconsoleHandlerとrotatingfileHandlerのふたつが設定されていますので、コンソール上とlog.txtの両方に出力されます。test1はconsoleHandlerのみですので、コンソールのみ。test2はrotatingfileHandlerのみですので、log.txtのみにログが出力されています。出力の形式はfomatterで設定した形式になります。 logging full function

これでかなり柔軟にログ出力できるようになりました。マルチスレッド等で、全て同じログ形式でよければ、全て名前を指定しないrootロガーを使えばよいです。個別に設定したいときは、Configファイルの'loggers'に名前を登録して、スレッド側でもlogging.getLogger(登録した名前)でロガーを呼び出せば、そのスレッドのログだけ個別に設定することができます。

ログは開発時や問題発生時に役に立ちますので、loggingモジュールを使いこなせるようになっておくと便利です。

ラズパイ ソフトウェアに戻る
トップページに戻る