サーチ…


Pythonロギングの概要

このモジュールは、アプリケーションとライブラリ用の柔軟なイベントロギングシステムを実装する関数とクラスを定義します。

標準ライブラリモジュールによって提供されるロギングAPIを持つ主要な利点は、すべてのPythonモジュールがロギングに参加できるため、アプリケーションログにサードパーティ製のモジュールからのメッセージと統合された独自のメッセージを含めることができることです。

だから、始めることができます:

コードの直接の構成例

import logging

logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

logger.debug('this is a %s test', 'debug')

出力例:

2016-07-26 18:53:55,332 root         DEBUG    this is a debug test

INIファイルによる設定例

ファイルの名前がlogging_config.iniであると仮定します。ファイル形式の詳細については、 ロギングチュートリアルの ロギング設定セクションを参照してください

[loggers]
keys=root

[handlers]
keys=stream_handler

[formatters]
keys=formatter

[logger_root]
level=DEBUG
handlers=stream_handler

[handler_stream_handler]
class=StreamHandler
level=DEBUG
formatter=formatter
args=(sys.stderr,)

[formatter_formatter]
format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s

次に、コード内でlogging.config.fileConfig()を使用します。

import logging
from logging.config import fileConfig

fileConfig('logging_config.ini')
logger = logging.getLogger()
logger.debug('often makes a very good meal of %s', 'visiting tourists')

辞書による設定例

Python 2.7以降では、設定の詳細を持つ辞書を使用できます。 PEP 391には、構成ディクショナリ内の必須およびオプションの要素のリストが含まれています。

import logging
from logging.config import dictConfig

logging_config = dict(
    version = 1,
    formatters = {
        'f': {'format':
              '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
        },
    handlers = {
        'h': {'class': 'logging.StreamHandler',
              'formatter': 'f',
              'level': logging.DEBUG}
        },
    root = {
        'handlers': ['h'],
        'level': logging.DEBUG,
        },
)

dictConfig(logging_config)

logger = logging.getLogger()
logger.debug('often makes a very good meal of %s', 'visiting tourists')

例外のロギング

例外を記録する場合は、 logging.exception(msg)メソッドを使用することができます。

>>> import logging
>>> logging.basicConfig()
>>> try:
...     raise Exception('foo')
... except:
...     logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: foo

引数として例外を渡さないでください:

logging.exception(msg)msg argを期待しているので、以下のようにロギング呼び出しに例外を渡すのは一般的な落とし穴です:

>>> try:
...     raise Exception('foo')
... except Exception as e:
...     logging.exception(e)
...
ERROR:root:foo
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: foo

これが最初にやるべきことであるかのように見えるかもしれませんが、実際には、例外とさまざまなエンコーディングがロギングモジュールでどのように連携するのかという問題があります。

>>> try:
...     raise Exception(u'föö')
... except Exception as e:
...     logging.exception(e)
...
Traceback (most recent call last):
  File "/.../python2.7/logging/__init__.py", line 861, in emit
    msg = self.format(record)
  File "/.../python2.7/logging/__init__.py", line 734, in format
    return fmt.format(record)
  File "/.../python2.7/logging/__init__.py", line 469, in format
    s = self._fmt % record.__dict__
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
Logged from file <stdin>, line 4

ユニコード文字を含む例外をログに記録しようとすると、この方法では悲惨失敗します。これは、元の例外のstacktraceを、 logging.exception(e)呼び出しのフォーマット中に発生した新しいもので上書きすることによって隠すでしょう。

明らかに、あなた自身のコードでは、例外のエンコーディングを知っているかもしれません。しかし、サードパーティ製のライブラリでは、これを別の方法で処理する可能性があります。

正しい使用法:

例外の代わりに、単にメッセージを渡して、Pythonにその魔法をさせるなら、それはうまくいくでしょう:

>>> try:
...     raise Exception(u'föö')
... except Exception as e:
...     logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6

この場合、実際にはeを使用しないので、 logging.exception(...)呼び出すと、最新の例外が魔法のようにフォーマットされます。

ERROR以外のログレベルによる例外のロギング

ERRORよりも別のログレベルで例外をログに記録する場合は、デフォルトのロガーのexc_info引数を使用できます。

logging.debug('exception occurred', exc_info=1)
logging.info('exception occurred', exc_info=1)
logging.warning('exception occurred', exc_info=1)

例外のメッセージへのアクセス

ライブラリーは、ユニコードまたは(あなたが運が良ければ、utf-8の)バイト文字列のいずれかとして、メッセージとともに例外をスローする可能性があることに注意してください。本当に例外のテキストにアクセスする必要がある場合は、 repr(e)または%r文字列の書式設定を使用するだけです。

>>> try:
...     raise Exception(u'föö')
... except Exception as e:
...     logging.exception('received this exception: %r' % e)
...
ERROR:root:received this exception: Exception(u'f\xf6\xf6',)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow