在Python中记录一个堆栈级别的模块名称/行

时间:2012-04-05 10:57:24

标签: python logging

我写了一个包装器记录器类,它在属性中保留self.logger=getLogger(...)的返回值,并相应地调用记录请求(self.logger.info(...))。在处理程序格式中,我使用标记%(module)s%(lineno)d来打印模块名称和行号。不幸的是,我只在行号中获得了包装器模块名称,因为这是对日志系统的最终调用发生的地方。

您是否知道如何使用模块名称和行号来报告函数,而不是调用包装器?

2 个答案:

答案 0 :(得分:2)

虽然我同意如上所述使用包装器有点傻,但我自己解决了这个问题,因为当使用lambda来包装在“extras”中具有相似,冗长和烦人参数的调用时。在其他地方找不到好的答案,我以为我会分享。

(这是一个Python 3.2.3解决方案。再次,它特定于lambda包装器而不是类包装器。)

第一步:查找Python源代码,找到..Lib \ logging \ __ init__.py,
步骤b:找到“Logger.findCaller”方法,将其复制到某处的实用程序文件中,重命名为“find_caller_no_lambda”。
下一步:从方法签名中删除“self”,为任何模块级别属性添加前缀,并进行以下更改,修改后尝试:

#       if filename == _srcfile: # Original line
        if filename == logging._srcfile or f.f_code.co_name == "<lambda>": # New line
            f = f.f_back # Original line for context.
            continue # Original line for context.

最后一步:声明记录器的任何地方,插入以下行:

my_logger.findCaller = util.find_caller_no_lambda

瞧。

(当然,如果您愿意,可以将Logger子类化为一个小改动。)

附录:

相反,您可以重写Logger.makeRecord以删除对额外内容中的键冲突的检查,并将行号,函数名称等添加到日志调用本身/在包装器中检测此类内容。

答案 1 :(得分:0)

它在Python Frame对象中。 http://docs.python.org/library/inspect.html