「C#によるlog4netの実装」でC#によるロギング機能をlog4netで実装しましたが、pythonによリ次のロギング機能をloggingモジュールで実装します。
- ロギングの書式は、タイムスタンプ、モジュール名、ライン番号を付与します。
- 世代管理を行います。
- 複数のファイルに分割されたモジュールからのログを一つのログファイルにロギングします。
- 例外発生時の例外メッセージをロギングします。
二つのファイル「logtest.py」「moduleA.py」に分割したpythonスクリプトを次に示します。
logtest.py
# -*- coding: utf-8 -*- import logging.config import moduleA def main(): # ログ設定ファイルからログ設定を読み込み logging.config.fileConfig('logging.conf') logger = logging.getLogger() logger.debug('debug') logger.info('info') logger.warning('warning') logger.error('error') logger.critical('critical') moduleA.add(1, 2) try: 1/0 except Exception as e: logging.exception('Exception') if __name__ == '__main__': main()
moduleA.py
import logging.config # ログ設定ファイルからログ設定を読み込み logging.config.fileConfig('logging.conf') logger = logging.getLogger() def add(x, y): logger.info( x + y)
ログのレベルを次に示します。このレベルを設定することにより上位のレベルはログされなくなります。
名前 | 設定値 | 役割 |
---|---|---|
NOTSET | 0 | 設定値などの記録(全ての記録) |
DEBUG | 10 | 動作確認などデバッグの記録 |
INFO | 20 | 正常動作の記録 |
WARNING | 30 | 警告の記録 |
ERROR | 40 | エラーなど重大な問題 |
CRITICAL | 50 | 停止など致命的な問題 |
ロギングの設定ファイル「logging.conf」を次に示します。
logging.conf
[loggers] keys=root [handlers] keys=consoleHandler, fileHandler [formatters] keys=logFormatter [logger_root] level=DEBUG handlers=consoleHandler, fileHandler [handler_consoleHandler] class=logging.StreamHandler formatter=logFormatter args=(sys.stdout, ) [handler_fileHandler] class=handlers.RotatingFileHandler formatter=logFormatter args=('./log/test.log','a', (100), 3) [formatter_logFormatter] class=logging.Formatter format=%(asctime)s %(filename)s:%(lineno)d %(message)s
設定ファイルには次の項目が必要になります。
- [loggers] 「keys=」の後に任意のlogger名を記述。「root」は必須。
- [handlers] 「keys=」の後に任意のhandler名を記述。
- [formatters] 「keys=」の後に任意のformatter名を記述。
次に「keys=」で定義したlogger名、handler名、formatter名を記述していきます。
[logger_logger名] ロガーにハンドラーの追加
[handler_handler名] ハンドラーの設定
[formatter_formatter名] フォーマッターの設定
作成したpythonスクリプトを次のコマンドで実行します。フォルダ「log」のファイル「test.log」に表示されたログと同じ内容が記録されます。
$ python3 logtest.py 2017-12-12 07:55:43,107 logtest.py:12 debug 2017-12-12 07:55:43,113 logtest.py:13 info 2017-12-12 07:55:43,114 logtest.py:14 warning 2017-12-12 07:55:43,114 logtest.py:15 error 2017-12-12 07:55:43,115 logtest.py:16 critical 2017-12-12 07:55:43,115 moduleA.py:9 3 2017-12-12 07:55:43,116 logtest.py:23 Exception Traceback (most recent call last): File “logtest.py”, line 21, in main 1/0 ZeroDivisionError: division by zero
ロギングの書式
次のロギングの書式により、タイムスタンプ、モジュール名、ライン番号をログメッセージに付与します。
format=%(asctime)s %(filename)s:%(lineno)d %(message)s
そのほかに設定できる項目を次に示します。
フォーマット | 役割 |
---|---|
%(asctime)s | 実行時刻 |
%(filename)s | ファイル名 |
%(funcName)s | 行番号 |
%(levelname)s | ログの定義 |
%(lineno)d | ログレベル名 |
%(message)s | ログメッセージ |
%(module)s | モジュール名 |
%(name)s | 関数名 |
%(process)d | プロセスID |
%(thread)d | スレッドID |
世代管理
世代管理は、次に示すログのローテート機能を使います。
class=handlers.RotatingFileHandler args=(‘./log/test.log’,’a’, (100), 3)
書式を次に示します。
class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False) maxBytes:1ファイルにログする最大バイト数 backupCount:世代数
そのほかに、特定の時間間隔により分割する次のローテート設定「TimedRotatingFileHandler」もあります。
class logging.handlers.TimedRotatingFileHandler(filename, when=’h’, interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)
次に、実際に世代管理されたファイル群、3ファイルを示します。最新のログは「test.log」に保存されます。
複数ファイルに渡るロギング
複数のファイルに分割されたモジュールからのログを一つのログファイルにロギングします。これは特に意識せずに、次のようにファイルごとに再宣言すれば同じログファイルに追加されていきます。
import logging.config logging.config.fileConfig('logging.conf') logger = logging.getLogger()
例外メッセージのロギング
例外発生時の例外メッセージは、次の関数「logging.exception」を使用してロギングします。
try: ・・・ except Exception as e: logging.exception('Exception')