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诀窍是用用异常处理子句包装调用的函数替换非常基本的记录字符串格式化的函数。
确保在使用 logger 之前进行了此替换。此替换也适用于您程序的其他模块。

所以你的例子会被这样修改:请注意我修改了一些代码以确保会生成异常。

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

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

于 2013-01-11T02:27:55.163 回答