在python日志库中找到"没有足够的参数......"的简单方法

Pio*_*pla 7 python debugging

您是否知道任何简单的方法来查找"没有足够的格式字符串争论"的日志记录调用.在我的工作站上,我已修改logging/__init__.py为打印msg,以便我可以轻松找到源代码中的行.

但是,您是否知道如何在测试环境中做什么,您无法更改python标准库,也无法轻松运行pdb?

注意:回溯没有意义,日志记录库也很谨慎.这是一个追溯:

  File "/usr/lib/python2.6/logging/handlers.py", line 71, in emit
    if self.shouldRollover(record):
  File "/usr/lib/python2.6/logging/handlers.py", line 144, in shouldRollover
    msg = "%s\n" % 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 enough arguments for format string
Run Code Online (Sandbox Code Playgroud)

这是标准库中捕获错误的代码

    try:
        if self.shouldRollover(record):
            self.doRollover()
        logging.FileHandler.emit(self, record)
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        self.handleError(record)
Run Code Online (Sandbox Code Playgroud)

Alex建议的解决方案: 我已经包装了getMessage来打印msg和args.这是代码:

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)
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 2

一般来说,捕获异常(包括您提到的异常)的最佳方法是将可疑代码放在/语句try的子句中;在子句中你可以使用模块或其他方式来查明错误的语句。tryexceptexcepttraceback

否则未捕获的异常最终会出现在sys.excepthook中,这是您可以在需要时用于获取回溯的另一种方法。

然而,我不认为该logging模块有一种架构方式来告诉它“让异常传播”——在这种情况下,你最好的选择,尽管可能很肮脏,可能是猴子修补。换句话说,您通常可以在运行时“更改Python标准库”——通过将其中的标识符设置为您自己的函数/类/等包装标准函数/类等。例如,如果您知道问题出在调用上logging.warning,“概念证明”monkeypatch 可能是:

import logging, traceback

orgwarn = logging.warning
def mywarn(msg, *a):
  try: res = msg % a
  except TypeError:
    traceback.print_exc()
  return orgwarn(msg, *a)
logging.warning = mywarn
Run Code Online (Sandbox Code Playgroud)

有更简洁的方法,但它们可能有点麻烦(例如,创建自己的记录器类并将其设置为根记录器)。猴子补丁并不是在生产环境中操作的好方法(它对系统升级很脆弱,可能难以理解和维护等),但对于调试和测试目的来说是可以接受的。