Pythonのログの仕組み

ややこしかったので、ここにメモしておく。(参考:Logging HOWTO

loggingライブラリでログ出力をなんやかんや制御できる。

loggingライブラリは、ロガー、ハンドラ、フィルタ、フォーマッタという部品からなる。この4つの働きと関係性を把握しないとわけが分からなくなる。

  • ロガーは、アプリケーションコードが直接使うインターフェースを公開します。

  • ハンドラは、(ロガーによって生成された) ログ記録を適切な送信先に送ります。(要は、ログ出力先が画面コンソールか、ファイル書き出しかなどを定義する)

  • フィルタは、どのログ記録を出力するかを決定する、きめ細かい機能を提供します。

  • フォーマッタは、ログ記録が最終的に出力されるレイアウトを指定します。(要は、ログ出力するときのフォーマットなどを定義。例えば日付のyyy-mm-ddなど)

下記の絵がロガー、ハンドラ、フィルタ、フォーマッタの関係が書かれており、イメージしやすい。

Sample ローテートするログファイルを、フォーマット指定して定義

import logging
import logging.handlers

# create logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.handlers.RotatingFileHandler(‘APL.log’, mode=’a’,maxBytes=50, backupCount=5)
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’)

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# ‘application’ code
logger.debug(‘debug message’)
logger.info(‘info message’)
logger.warning(‘warn message’)
logger.error(‘error message’)
logger.critical(‘critical message’)

 

ーーー解説ーーーーーーーーー
import logging
import logging.handlers

# create logger
logger = logging.getLogger(‘example’) ここで定義したexampleという名前が、後述のフォーマッタで%(name)sと定義するとログに出力されるため、ロガー名だけで、どこでイベントのログが取られたか、直感的に明らかになる。これは、Logging HOWTOにも以下のように書かれている。
 

ガーに名前をつけるときの良い習慣は、ロギングを使う各モジュールに、以下のように名付けられた、モジュールレベルロガーを使うことです:

logger.setLevel(logging.DEBUG) —(1)
(1) ロガーが扱うログメッセージの最も低い深刻度を指定

# create console handler and set level to debug
ch = logging.handlers.RotatingFileHandler(‘APL.log’, mode=’a’,maxBytes=50, backupCount=5)-–(2)   ログファイルローテートするタイプのハンドラ。APL.logというログファイルが作成され、ファイルサイズが50バイトを超えると自動ローテートされ、ローテートのファイル数は最大5.5を超えると古いファイルから上書きされる。
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’)--(3)  書き出し文字列のフォーマット指定

# add formatter to ch
ch.setFormatter(formatter) フォーマットをハンドラにセット

# add ch to logger
logger.addHandler(ch) ハンドラをロガーにセット

# ‘application’ code
logger.debug(‘debug message’) これらのログ出力がファイルに書き出される
logger.info(‘info message’)
logger.warning(‘warn message’)
logger.error(‘error message’)
logger.critical(‘critical message’)

Python の属性

Python では、インスタンス変数やクラス変数、メソッドのことを「属性 (attribute) 」といいます。属性は名前で管理されていて、同じ名前のインスタンス変数とメソッドを同時に使うことはできません。インスタンス変数の方が優先されるため、メソッドを呼び出すことができなくなります。インスタンス変数はクラス変数やメソッドよりも優先されることに注意してください。

python unittest

unittestには
unittest.TestCaseクラスを継承したクラスにテストメソッドを記述
テストメソッドはtest_*で始める
というルール。これさえ守ればコマンドラインからテストを実行することが可能。

unittest用のディレクトリ構成
.
├─sample.py
└─tests
├─__init__.py
└─test_sample.py