2011-02-26 17 views
7

標準のPythonロギングモジュールを使用しているモジュールがたくさんあるとき、以下のスタックトレースは、Pythonロギングを使用する際にフォーマットエラーの原因を見つける

Traceback (most recent call last): 
    File "/usr/lib/python2.6/logging/__init__.py", line 768, in emit 
    msg = self.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 648, in format 
    return fmt.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 436, in format 
    record.message = record.getMessage() 
    File "/usr/lib/python2.6/logging/__init__.py", line 306, in getMessage 
    msg = msg % self.args 
TypeError: not all arguments converted during string formatting 

私はPythonのロギングモジュールを使用し始めているので、明らかに何かを見落としているかもしれません。私は、greenletsを使用しているためにスタックトレースが役に立たないのかどうか、またはこれがロギングモジュールには普通なら、どんな助けにも感謝します。私はソースを変更しても構わないと思いますが、ロギングライブラリを実際にどこに問題があるのか​​という手がかりを与えるようにするためには何もありません。

答えて

5

ロギングモジュールは、不正なログメッセージが残りのコードを停止させないようにするため、emitメソッドはエラーをキャッチし、メソッドhandleErrorに渡します。あなたがするのが最も簡単なのは、/usr/lib/python2.6/logging/__init__.pyを一時的に編集し、handleErrorを見つけることです。これは次のようになります。

def handleError(self, record): 
    """ 
    Handle errors which occur during an emit() call. 

    This method should be called from handlers when an exception is 
    encountered during an emit() call. If raiseExceptions is false, 
    exceptions get silently ignored. This is what is mostly wanted 
    for a logging system - most users will not care about errors in 
    the logging system, they are more interested in application errors. 
    You could, however, replace this with a custom handler if you wish. 
    The record which was being processed is passed in to this method. 
    """ 
    if raiseExceptions: 
     ei = sys.exc_info() 
     try: 
      traceback.print_exception(ei[0], ei[1], ei[2], 
             None, sys.stderr) 
      sys.stderr.write('Logged from file %s, line %s\n' % (
          record.filename, record.lineno)) 
     except IOError: 
      pass # see issue 5971 
     finally: 
      del ei 

一時的に編集します。最初に単純なraiseを挿入すると、エラーが飲み込まれるのではなくコードに反映されます。問題を修正したら、ロギングコードを元のものに復元してください。むしろインストールPythonのコードを編集し、あなたもこのようなエラーを見つけることができるよりも

6

ハンドラは、問題を与えているハンドラの1つである
def handleError(record): 
     raise RuntimeError(record) 
    handler.handleError = handleError 

。フォーマットエラーが発生すると、その場所が表示されます。

+0

これは恐ろしいことですが、ライブラリを編集することが完全に不可能な場合には覚えておく価値がありますので、+1。 – porgarmingduod

+0

@ porgarmingduod:偉大ではないが、それは標準liのソースを操作するよりも恐ろしいことではないブラジャー。 Monkey-patchingは同じプロセスの他のすべてに影響しますが、ライブラリの直接編集は同じシステム上の他のすべてに影響します。 –

1

独自のフォーマッタを作成することもできますが、どこにでも組み込む必要があります。

class DebugFormatter(logging.Formatter): 
    def format(self, record): 
     try: 
      return super(DebugFormatter, self).format(record) 
     except: 
      print "Unable to format record" 
      print "record.filename ", record.filename 
      print "record.lineno ", record.lineno 
      print "record.msg ", record.msg 
      print "record.args: ",record.args 
      raise 


FORMAT = '%(levelname)s %(filename)s:%(lineno)d %(message)s' 
formatter = DebugFormatter(FORMAT) 
handler = logging.StreamHandler() 
handler.setLevel(logging.DEBUG) 
handler.setFormatter(formatter) 
logger = logging.getLogger(__name__) 
logger.setLevel(logging.DEBUG) 
logger.addHandler(handler) 
3

質問に対する回答ではありませんが、私のようなロギングモジュールを使用した初心者になることを願っています。

私の問題は、私はそうprint('a',a)のような有効なラインがlogging.info('a',a)になった(しかし、それは代わりにlogging.info('a %s'%a)する必要があり、logging.infoで を印刷のすべての出現を置き換えるということでした。

これはまたHow to traceback logging errors?にほのめかしたが、それはdoesnのました研究に出てこない

+1

python 3.6の新しい構文: 'logging.info(f'a {a} ')' – JinSnow

+0

ありがとう、私はそれを見ていない! https://www.python.org/dev/peps/pep-0498/ – lib