今回は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という名前)は、上記フォーマットでコンソールにログ出力します。
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で設定した形式になります。
これでかなり柔軟にログ出力できるようになりました。マルチスレッド等で、全て同じログ形式でよければ、全て名前を指定しないrootロガーを使えばよいです。個別に設定したいときは、Configファイルの'loggers'に名前を登録して、スレッド側でもlogging.getLogger(登録した名前)でロガーを呼び出せば、そのスレッドのログだけ個別に設定することができます。
ログは開発時や問題発生時に役に立ちますので、loggingモジュールを使いこなせるようになっておくと便利です。