ロギング

  • DEBUGレベルはファイルへ、INFOレベル以上は標準出力にログさせたい場合
    1. 基本は logging.basicConfig で設定する
    2. 標準出力用のハンドラ(console)をStreamHandler()で設定する
    3. consoleハンドラ を グローバルななロガー(?) (logging.getLogger()) に追加する
  • ファイルへの出力は、FileHandler('filename')を使うことも可能だが、この場合だと日付フォーマットが指定できないので却下

import logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)-8s %(name)-12s %(module)s.%(funcName)-20s %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    filename='example.log',
                    filemode='a')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(levelname)-8s %(name)-12s %(module)s.%(funcName)-20s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)

## __________________________________________________
class LogExDayo(object):

    ## __________________________________________________
    def __init__(self):
        ...
        self.logger = logging.getLogger('LogExDayo')
        self.logger.debug('-' * 50)

    ## __________________________________________________        
    def read(self, ifn):
        ## exit if file does not exists
        if not os.path.exists(ifn):
            self.logger.error('file "%s" does not exist.', ifn)
            sys.exit(-1)
        ## read file
        ## ...

    ## __________________________________________________    
    def run(self):
        self.logger.info('start')
        # ... process ...
        self.logger.info('finished)

## __________________________________________________ 
if __name__ == '__main__':
    l = LogExDayo()
    l.read('read_this_file.txt')
    l.run()

  • basicConfigは、debug()や、info()などが呼ばれるに設定して置かなければいけない

>>> import logging
>>> help(logging.basicConfig)

attribute default value description
filename - ログ出力先のファイル名を指定; streamより優先される
filemode a ファイルに書き込む方法を指定; [a, w]
format logging.BASIC_FORMAT 書式設定; 詳細は help(logging.Formatter)参照
datefmt - 時刻(asctime)の書式設定
level logging.WARNING ログレベルの設定; [NOTSET, DEBUG, INFO, WARNING, CRITICAL, FATAL]
stream sys.stderr StreamHandlerを設定; [sys.stderr, sys.stdout]
  • helpに書いてあったけれど、streamでファイルを指定することも可能だけれど、ファイルクローズされないのでやらないほうがいい

logging.basicConfig(stream=open(filename, 'w'))  ## <== ファイルクローズ機能はない

## オプション解析は、optparse.OptionParserを使ってみる
parser = OptionParser(usage)
parser.add_option(-l, --log,
                  dest='loglevel',
                  help='set log level. ex) --log=DEBUG or --log=debug.')
## これ以降で、オプションのloglevelの値を確認し、basicConfigに設定
## 値が正しくない場合は、ValueErrorでエラー処理
numeric_level = getattr(logging, loglevel.upper(), None)
if not is instance(numeric_level, int):
    raise ValueError('Invalid log level : %s' % log level)
logging.basicConfig(level=numeric_level, ...)

  • 2つの方法で、ログ出力のレベルを設定できる
    1. loggingの初期値として設定
    2. logging.Loggerオブジェクト(以下Loggerオブジェクト)を作成し、それに対して設定
      • Loggerオブジェクトはlogging.getLogger(name)でインスタンス化する決まり

## loggingモジュールの初期設定
logging.basicConfig(level=logging.DEBUG)

## Loggerオブジェクトを作ってから設定
logger = logging.getLogger('somelogger')
logger.setLevel(logging.DEBUG)

  • 設定したログレベル以上のメッセージが出力される
    • DEBUGの場合:DEBUG, INFO, ERROR, CRITICAL, FATAL
    • ERRORの場合:ERROR, CRITICAL, FATAL
  • 出力レベルは、各ファイルハンドラ(i.e. ログファイル、コンソール)に応じて変更可能

logging.NOTSET   # = 0
logging.DEBUG    # = 10
logging.INFO     # = 20
logging.WARNING  # = 30
logging.ERROR    # = 40
logging.CRITICAL # = 50
logging.FATAL    # = 50

  • ログメッセージの表示先、記録先を、ログレベルに応じて切り替える場合に使う
  • StreamHandler
  • FileHandler
  • fileConfig()
  • dictConfig()