4

ロギングモジュールを使用して、アプリケーションにメッセージを記録します。

フォーマット文字列またはパラメータを間違えるとエラーが発生することがよくあります。たとえば、次のようになります。

import logging
my_log = logging.getLogger("MyLog")
# this is obviously wrong
my_log.info('%d', "abc")

結果は、以下のようなエラーになります。

Traceback (most recent call last):
  File "/usr/lib64/python2.6/logging/__init__.py", line 776, in emit
    msg = self.format(record)
  File "/usr/lib64/python2.6/logging/__init__.py", line 654, in format
    return fmt.format(record)
  File "/usr/lib64/python2.6/logging/__init__.py", line 436, in format
    record.message = record.getMessage()
  File "/usr/lib64/python2.6/logging/__init__.py", line 306, in getMessage
    msg = msg % self.args
TypeError: %d format: a number is required, not str

ただし、ロギングモジュール内のトレースバックを示しているだけです。コード内のどこでエラーが発生したかはわかりません。

それを修正する方法はありますか?

4

1 に答える 1

3

エラーの原因を見つける際にも同じ問題が発生しました。ロギングモジュールはそのような例外を処理し、プログラムを停止しません-これはログモジュールの許容可能な動作です。ただし、例外を抑制し、処理中に十分な情報を提供しません。

ここで説明したシックを見つけて使用しています

秘訣は、文字列のフォーマットlogging.LogRecord.getMessageを行う非常に基本的なロギング関数を、例外処理句で呼び出しをラップする関数に置き換えることです。
ロガーを使用する前に、この交換を行ったことを確認してください。この置換は、プログラムの他のモジュールでも機能します。

したがって、例は次のように変更されます。例外が生成されるように、コードを少し変更したことに注意してください。

def print_log_record_on_error(func):
    def wrap(self, *args, **kwargs):
        try:
            return func(self, *args, **kwargs)
        except:
            import sys
            print >>sys.stderr, "Unable to create log message msg=%r, args=%r " % (
                getattr(self, 'msg', '?'), getattr(self, 'args', '?'))
            raise
    return wrap
import logging
logging.LogRecord.getMessage = print_log_record_on_error(logging.LogRecord.getMessage)

logging.basicConfig()
my_log = logging.getLogger("MyLog")
# this is obviously wrong
my_log.error('%d' , "abc")

そして、それは今より有用な例外を生成します:

Unable to create log message msg='%d', args=('abc',) 
Traceback (most recent call last):
  File "C:\Progs\Python262\Lib\logging\__init__.py", line 760, in emit
    msg = self.format(record)
  File "C:\Progs\Python262\Lib\logging\__init__.py", line 644, in format
    return fmt.format(record)
  File "C:\Progs\Python262\Lib\logging\__init__.py", line 432, in format
    record.message = record.getMessage()
  File "C:/Users/vvlad/PycharmProjects/stackoverflow/test1.py", line 6, in wrap
    return func(self, *args, **kwargs)
  File "C:\Progs\Python262\Lib\logging\__init__.py", line 302, in getMessage
    msg = msg % self.args
TypeError: %d format: a number is required, not str

ログを集中的に使用するアプリケーションを使用している場合は、loggin関数を置き換えるオプションを追加することをお勧めします。したがって、oinデバッグモードコードはオーバーロードされた関数を使用しますが、本番環境では使用されないため、もう1つの例外処理によるパフォーマンスの低下を回避できます。

于 2013-01-11T02:27:55.163 に答える