使用python日志记录时查找格式错误的来源

时间:2011-02-26 15:47:30

标签: python debugging logging stack-trace

当我使用标准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 个答案:

答案 0 :(得分:6)

您可以找到如下错误:

,而不是编辑已安装的python代码
    def handleError(record):
        raise RuntimeError(record)
    handler.handleError = handleError

其中handler是提供问题的处理程序之一。现在,当格式错误发生时,您将看到位置。

答案 1 :(得分: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应该可以确保错误在代码中传播而不是被吞下。一旦解决了问题,只需将日志代码恢复到原来的状态即可。

答案 2 :(得分:3)

这不是问题的答案,但希望像我这样的日志记录模块的其他初学者。

我的问题是我用logging.info替换了所有出现的print, 所以print('a',a)之类的有效行变为logging.info('a',a)(但它应该是logging.info('a %s'%a)

这也在How to traceback logging errors?暗示,但研究中没有提到

答案 3 :(得分: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)

答案 4 :(得分:0)

遇到相同的问题 由于格式名称错误而产生这种回溯。因此,在为日志文件创建格式时,请在python文档中检查一次格式名称:“ https://docs.python.org/3/library/logging.html#formatter-objects