我写了一个包装记录器类,它将 self.logger=getLogger(...)
的返回值保存在一个属性中,并相应地调用日志记录请求(self.logger.info( ...)
)。在处理程序格式中,我使用标记 %(module)s
和 %(lineno)d
来打印模块名称和行号。不幸的是,我只在行号中获得包装器模块名称,因为这是对日志系统的最终调用发生的地方。
您知道如何使用模块名称和调用包装器的行号来报告函数吗?
最佳答案
虽然我同意使用所描述的包装器有点愚蠢,但我自己解决了这个问题,因为当使用 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 以删除对 extras 中的键冲突的检查,并将行号、函数名称等添加到日志调用本身/在包装器中检测此类内容。
关于python - 在 Python 中记录一个堆栈级别更高的模块名称/行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10027295/