使用Python记录

问题描述:

当我有很多使用标准Python记录模块不同的模块时发现格式错误的根源,以下堆栈跟踪无助于帮我找出,正好,我有一个格式错误的日志语句:使用Python记录

Traceback (most recent call last): 
    File "/usr/lib/python2.6/logging/__init__.py", line 768, in emit 
    msg = self.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 648, in format 
    return fmt.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 436, in format 
    record.message = record.getMessage() 
    File "/usr/lib/python2.6/logging/__init__.py", line 306, in getMessage 
    msg = msg % self.args 
TypeError: not all arguments converted during string formatting 

我才刚刚开始使用Python的日志记录模块,所以也许我忽视的东西明显。我不知道如果堆栈跟踪是无用的,因为我使用greenlets,或者如果这是正常的日志记录模块,但任何帮助,将不胜感激。我愿意修改源代码,任何可以让日志库实际上给出问题出在哪里的线索。

日志记录模块设计用于阻止错误的日志消息以杀死其余代码,因此emit方法捕获错误并将它们传递给方法handleError。为你做最简单的事情将是暂时编辑/usr/lib/python2.6/logging/__init__.py,并找到handleError。它看起来像这样:

def handleError(self, record): 
    """ 
    Handle errors which occur during an emit() call. 

    This method should be called from handlers when an exception is 
    encountered during an emit() call. If raiseExceptions is false, 
    exceptions get silently ignored. This is what is mostly wanted 
    for a logging system - most users will not care about errors in 
    the logging system, they are more interested in application errors. 
    You could, however, replace this with a custom handler if you wish. 
    The record which was being processed is passed in to this method. 
    """ 
    if raiseExceptions: 
     ei = sys.exc_info() 
     try: 
      traceback.print_exception(ei[0], ei[1], ei[2], 
             None, sys.stderr) 
      sys.stderr.write('Logged from file %s, line %s\n' % (
          record.filename, record.lineno)) 
     except IOError: 
      pass # see issue 5971 
     finally: 
      del ei 

现在暂时编辑它。在开始插入简单raise应保证误差会将会传播起来,而不是被吞噬你的代码。一旦解决了问题,只需将日志记录代码恢复到原来的状态即可。

而不是编辑安装Python代码,你也可以找到这样的错误:

def handleError(record): 
     raise RuntimeError(record) 
    handler.handleError = handleError 

其中处理器是为有问题的处理器之一。现在,当格式错误发生时,你会看到位置。

+0

那么,这是一个可怕的方法,但是,对于编辑库完全不可能的情况,这是一种值得记住的方法,所以+1。 – porgarmingduod 2011-09-30 10:46:58

+0

@porgarmingduod:猴子补丁可能不是很好,但比操纵标准李的来源更不可怕brary。猴子补丁会影响同一进程中的其他所有内容,但直接编辑库会影响同一系统中的其他所有内容。在Python 3.6 – 2013-01-06 23:21:49

或者你可以创建自己的格式,但你必须要处处包含它。

class DebugFormatter(logging.Formatter): 
    def format(self, record): 
     try: 
      return super(DebugFormatter, self).format(record) 
     except: 
      print "Unable to format record" 
      print "record.filename ", record.filename 
      print "record.lineno ", record.lineno 
      print "record.msg ", record.msg 
      print "record.args: ",record.args 
      raise 


FORMAT = '%(levelname)s %(filename)s:%(lineno)d %(message)s' 
formatter = DebugFormatter(FORMAT) 
handler = logging.StreamHandler() 
handler.setLevel(logging.DEBUG) 
handler.setFormatter(formatter) 
logger = logging.getLogger(__name__) 
logger.setLevel(logging.DEBUG) 
logger.addHandler(handler) 

这不是一个真正的问题的答案,但希望这将是其他像我这样的日志记录模块的初学者。

我的问题是,我替换logging.info打印的所有事件, 所以像print('a',a)有效的行成为logging.info('a',a)(但它应该是logging.info('a %s'%a)代替。

这也暗示在How to traceback logging errors?,但它不不要出现在研究中

+1

新语法:'logging.info(f'a {A}“)' – JinSnow 2017-03-24 14:01:58

+0

感谢,我没有看进去! https://www.python.org/dev/peps/pep-0498/ – lib 2017-03-25 11:31:46