【问题标题】:Finding the source of format errors when using python logging使用 python 日志记录时查找格式错误的来源
【发布时间】:2011-07-04 21:54:54
【问题描述】:

当我使用标准 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,或者这对于日志记录模块是否正常,但任何帮助将不胜感激。我愿意修改源代码,任何能让日志库真正提供问题所在的线索。

【问题讨论】:

    标签: python debugging logging stack-trace


    【解决方案1】:

    日志记录模块旨在阻止错误的日志消息杀死其余代码,因此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 应该确保错误在您的代码中传播而不是被吞没。解决问题后,只需将日志记录代码恢复到原来的状态即可。

    【讨论】:

      【解决方案2】:

      除了编辑安装的python代码,你还可以找到这样的错误:

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

      其中 handler 是导致问题的处理程序之一。现在,当出现格式错误时,您会看到位置。

      【讨论】:

      • 嗯,这是一种可怕的做法。不过,对于那些完全不可能编辑库的情况,这是一种值得记住的方法,所以 +1。
      • @porgarmingduod:猴子补丁可能不是很好,但它并不比操纵标准库的源代码更可怕。 Monkey-patching 会影响同一进程中的所有其他内容,但直接编辑库会影响同一系统上的所有其他内容。
      【解决方案3】:

      或者,您可以创建自己的格式化程序,但您必须在任何地方都包含它。

      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)
      

      【讨论】:

        【解决方案4】:

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

        我的问题是我用 logging.info 替换了所有出现的 print , 所以像print('a',a) 这样的有效行变成了logging.info('a',a)(但它应该是logging.info('a %s'%a)

        How to traceback logging errors? 也暗示了这一点,但并未在研究中提出

        【讨论】:

        【解决方案5】:

        遇到同样的问题 由于格式名称错误,会出现这样的 Traceback。因此,在为日志文件创建格式时,请在 python 文档中检查一次格式名称:“https://docs.python.org/3/library/logging.html#formatter-objects

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-11
          • 1970-01-01
          • 2013-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多