在python中获得更有用的'logging'模块错误输出

时间:2011-08-01 12:53:22

标签: python python-3.x

我正在使用python的logger模块(python版本3.x,但它无关紧要),我注意到格式字符串中的错误报告如下:

Traceback (most recent call last):
  File "/usr/lib/python3.1/logging/__init__.py", line 770, in emit
    msg = self.format(record)
  File "/usr/lib/python3.1/logging/__init__.py", line 650, in format
    return fmt.format(record)
  File "/usr/lib/python3.1/logging/__init__.py", line 438, in format
    record.message = record.getMessage()
  File "/usr/lib/python3.1/logging/__init__.py", line 308, in getMessage
    msg = msg % self.args
TypeError: %d format: a number is required, not str

正如您所看到的,没有提到实际错误(在我的代码中)的位置。顺便说一句,这是我的代码中的错误:

logging.debug('This is a string %d', str(foo))

更改%d中的%s解决了问题。

我的问题是:我如何从logging模块输出中获得一些稍微有用的信息?我是否必须编写自己的记录器?我在哪里调整logger模块?

2 个答案:

答案 0 :(得分:2)

如果我理解正确,那么这里的问题是回溯没有给出任何指示错误源自代码的位置。不知怎的,你必须追踪这条线

logging.debug('This is a string %d', str(foo))

自己。

日志记录模块的设计使得在emit()调用期间发生的异常由处理程序的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.
    """

您可以覆盖此方法以查看完整的回溯:

    import sys
    import logging

    class MyStreamHandler(logging.StreamHandler):
        def handleError(self, record):
            raise

    if __name__ == '__main__':
        console = MyStreamHandler()
        logger=logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)
        logger.addHandler(console)
        logger.debug('%d','ahh')

产量

Traceback (most recent call last):
  File "/tmp/test.py", line 25, in <module>
    logger.debug('%d','ahh')
  File "/usr/lib/python2.6/logging/__init__.py", line 1036, in debug
    self._log(DEBUG, msg, args, **kwargs)
  File "/usr/lib/python2.6/logging/__init__.py", line 1165, in _log
    self.handle(record)
  File "/usr/lib/python2.6/logging/__init__.py", line 1175, in handle
    self.callHandlers(record)
  File "/usr/lib/python2.6/logging/__init__.py", line 1212, in callHandlers
    hdlr.handle(record)
  File "/usr/lib/python2.6/logging/__init__.py", line 673, in handle
    self.emit(record)
  File "/usr/lib/python2.6/logging/__init__.py", line 796, in emit
    self.handleError(record)
  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: %d format: a number is required, not str

而使用通常的StreamHandler,只得到:

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: %d format: a number is required, not str

答案 1 :(得分:2)

当Unutbu打败我的时候正准备发布这个帖子。但无论如何它在这里:

您可以尝试子类化您正在使用的任何处理程序(下面使用StreamHandler示例)并使用在try:block

中包装它的函数覆盖format方法
import traceback, logging

class MyStreamHandler(logging.StreamHandler):
    def format(self, record):
        try:
            return logging.StreamHandler.format(self, record)
        except TypeError:
            # Print a stack trace that includes the original log call
            traceback.print_stack() 


if __name__ == "__main__":
    log = logging.getLogger("testlogger")
    handler = MyStreamHandler()

    log.addHandler(handler)

    log.error("Try interpolating an int correctly: %i", 1)

    log.error("Now try passing a string to an int: %d", 'abc')

    log.error("And then a string to a string %s", 'abc')

给了我:

Try interpolating an int correctly: 1
  File "logtest2.py", line 19, in ?
    log.error("Now try passing a string to an int: %d", 'abc')
  File "/usr/lib64/python2.4/logging/__init__.py", line 999, in error
    apply(self._log, (ERROR, msg, args), kwargs)
  File "/usr/lib64/python2.4/logging/__init__.py", line 1079, in _log
    self.handle(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 1089, in handle
    self.callHandlers(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 1126, in callHandlers
    hdlr.handle(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 642, in handle
    self.emit(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 731, in emit
    msg = self.format(record)
  File "logtest2.py", line 8, in format
    traceback.print_stack()
None
And then a string to a string abc

我不会将其留在任何生产代码中,但它应该可以帮助您找到类似

的内容
log.error("%d", 'a string')