问题描述
我使用模块在我的应用程序上记录消息。
我经常遇到格式字符串或参数错误导致错误的情况,例如:
import logging
my_log = logging.getLogger(MyLog)
#这显然是错误的
my_log.info('%d',abc )
结果是类似于下面的错误:
$
文件/usr/lib64/python2.6/logging/__init__.py,第776行,排除
msg = self.format(record)
文件/usr/lib64/python2.6/logging/__init__.py,行654,格式为
return fmt.format(record)
文件/usr/lib64/python2.6/logging/__init__.py,第436行,格式为
record.message = record.getMessage()
文件/ usr / lib64 /python2.6/logging/__init__.py,第306行,getMessage
msg = msg%se lf.args
TypeError:%d格式:一个数字是必需的,而不是str
,它只是显示了记录模块内的追溯;它没有告诉我错误发生在我的代码中。
有没有办法解决这个问题?
我在找到错误源时遇到了同样的问题。日志记录模块处理这种异常并且不停止程序 - 这是日志模块的可接受的行为。但是抑制异常,并且在处理它时不提供足够的信息。
我发现现在使用了这个粗体描述的
诀窍是替换基本的日志记录功能,执行字符串格式化 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无法创建日志消息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)
#这显然是错误的
my_log.error('%d',abc)
它会产生更多有用的e xception现在:
无法创建日志消息msg ='%d',args =('abc')
追溯(最近的最后一次呼叫):
文件C:\Progs\Python262\Lib\logging\__init __。py,第760行,发出
msg = self.format (记录)
文件C:\Progs\Python262\Lib\logging\__init __。py,行644,格式为
return fmt.format(record)
文件C:\Progs\Python262\Lib\logging\__init __。py,第432行,格式为
record.message = record.getMessage()
文件C:/ user / vvlad / PycharmProjects / stackoverflow / test1.py,第6行,wrap
返回func(self,* args,** kwargs)
文件C:\Progs\Python262\ lib\logging\__init __。py,第302行,在getMessage
msg = msg%self.args
TypeError:%d格式:一个数字是必需的,而不是str
如果您有日志密集型应用程序,我建议添加选项ce loggin功能与否。因此,调试模式代码将使用重载函数,但在生产中 - 不会因此避免再次执行异常处理的性能损失。
I use the logging module to log messages on my application.
Often I come to a situation where a mistake on a format string or parameter causes an error, for example:
import logging
my_log = logging.getLogger("MyLog")
# this is obviously wrong
my_log.info('%d', "abc")
The result is an error similar to the one below:
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
However, it just shows the traceback inside the logging module; it doesn't tell me where the error happened within my code.
Is there any way to fix that?
I experienced the same problems with finding the source of error. logging module handles such exceptions and do not stop the program - which is acceptable behavior for log module. But is suppress exception and do not provide sufficient information while handling it.
I found and now using the thick described here
The trick is to replace the very basic logging function that does string formatting logging.LogRecord.getMessage
with the function that wraps call with exception handling clause.
Make sure that you did this replacement before using logger.This replacement will work in other modules of your program too.
So your example would be modified like that:Please note that I modified code a little to ensure that exception will be generated.
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")
And it will produce more useful exception now:
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
If you have log intensive application I would suggest to add option to replace loggin function or not. Thus oin debug mode code will use overloaded function, but in production - it won't so you'll avoid performance penalty of one more exception handling.
这篇关于如何追溯记录错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!