我使用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
但是,它只显示了日志记录模块中的回溯;它没有告诉我代码中发生错误的位置。
有没有办法解决这个问题?
答案 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调试模式代码将使用重载函数,但在生产中 - 它不会这样,你将避免再一次异常处理的性能损失。