如何追溯记录错误?

时间:2012-11-19 17:33:43

标签: python debugging logging error-handling

我使用logging模块在​​我的应用程序上记录消息。

我常常遇到格式字符串或参数错误导致错误的情况,例如:

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

但是,它只显示了日志记录模块中的回溯;它没有告诉我代码中发生错误的位置。

有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:3)

我在找到错误来源时遇到了同样的问题。日志记录模块处理此类异常并且不会停止程序 - 这对于日志模块来说是可接受的行为。但是在处理它时会抑制异常并且不提供足够的信息。

我找到了,现在正在使用厚厚的here

诀窍是用包含异常处理子句调用的函数替换使用字符串格式化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

如果您有日志密集型应用程序,我建议添加替换登录功能的选项。因此oin调试模式代码将使用重载函数,但在生产中 - 它不会这样,你将避免再一次异常处理的性能损失。