当我第一次学习Python时,我习惯了这样做:
print "text", lineNumber, "some dictionary", my_dict
当我编写自己的日志记录工具时,我自然希望能够提供一个任意大小的项目列表,所以我这样做了:
def error(*args):
print ERR_PREFIX,
for _x in args:
print _x,
print "\r\n",
error("text", lineNumber, "some dictionary", my_dict)
现在我想开始使用日志包,因为它有更多的好处,我不想复制他们的努力。总的来说,它看起来像一个可以做很多事情的干净设计。但是我因为你不能再使用相同的项目列表来展示它而受到阻碍。相反,我必须将所有调用更改为更像这样的内容:
error("text %d some dictionary %s" % (lineNumber, my_dict))
或者,我可以做一些非常愚蠢的事情:
error(' '.join(map, str(("text", lineNumber, "some dictionary", my_dict))))
问题是,为什么省略这样一个明显的用例?如果你想从典型的“打印”声明直接转到新的日志记录设施,这不应该更容易吗?
作为后续问题,您能想到一种覆盖Logger类来执行此操作的方法吗?
答案 0 :(得分:7)
我建议最好将现有的日志消息更新为日志记录模块所期望的样式,因为对于查看代码的其他人来说,更容易,因为日志记录模块将不再按预期运行。
接下来,以下代码将使日志记录模块按您的需要运行。
import logging
import types
class ExtendedLogRecord(logging.LogRecord):
def getMessage(self):
"""
Return the message for this LogRecord.
Return the message for this LogRecord after merging any user-supplied
arguments with the message.
"""
if not hasattr(types, "UnicodeType"): #if no unicode support...
msg = str(self.msg)
else:
try:
msg = str(self.msg)
except UnicodeError:
msg = self.msg #Defer encoding till later
if self.args:
msg +=' '+' '.join(map(str,self.args))
return msg
#Patch the logging default logging class
logging.RootLogger.makeRecord=lambda self,*args: ExtendedLogRecord(*args)
some_dict={'foo':14,'bar':15}
logging.error('text',15,'some dictionary',some_dict)
输出:
ERROR:root:text 15 some dictionary {'foo': 14, 'bar': 15}
答案 1 :(得分:2)
修补日志包(建议作为一个答案)实际上是一个坏主意,因为这意味着其他代码(您没有编写,例如标准库中的内容)调用日志记录.error()将无法正常工作。
相反,您可以更改现有的error()函数来调用logging.error(),或者打印:
def error(*args):
logging.error('%s', ' '.join(map(str, args)))
(如果可能有unicode对象,你需要更加小心,但是你明白了。)
答案 2 :(得分:1)
您对记录的要求并不完全正确。
log= logging.getLogger( "some.logger" )
log.info( "%s %d", "test", value )
log.error("text %d some dictionary %s", lineNumber, my_dict)
您无需显式使用字符串格式化运算符%
修改强>
您可以利用原始的“错误”功能。
def error( *args ):
log.error( " ".join( map( str, args ) ) )
这可能会使转换变得不那么复杂。
您也可以这样做。
class MyErrorMessageHandler( object ):
def __init__( self, logger ):
self.log= logger
def __call__( self, *args ):
self.log.error( " ".join( map( str, args ) ) )
error= MyErrorMessageHandler( logging.getLogger("some.name") )
也可能是适口的。
答案 3 :(得分:0)
嗯,打印和记录是两回事。按理说,这样他们的用法可能也会有很大不同。
答案 4 :(得分:0)
add a method to a class动态相对容易。为什么不将您的方法添加到Logging。