Python logging配置:仅输出指定类日志 屏蔽第三方模块冗余日志
问题答案
两个问题的答案都是可行,有成熟的标准实现方案,以下是具体实现逻辑和可直接复用的代码:
Q1:是否存在可行方案,实现仅记录用户指定的单个类或指定类列表产生的日志?
存在,有两种常用实现路径:
- 推荐方案:业务代码打日志时不直接使用根logger,给每个需要输出日志的类绑定独立命名的专属logger,仅给这些专属logger配置输出规则、绑定输出handler,同时关闭这些logger的向上传播属性
propagate=False,没有配置输出的其他logger产生的日志自然不会被打印。这种方案性能最好,没有额外运行时开销。 - 兼容方案:如果不想改动原有日志调用逻辑,可以自定义日志过滤器
logging.Filter,挂载到输出handler上,在过滤器中通过日志记录的调用栈、类名、模块路径等信息判断日志来源,仅放行指定类产生的日志即可。
过滤器示例代码:import logging import inspect class AllowedClassFilter(logging.Filter): def __init__(self, allowed_classes): super().__init__() self.allowed = {cls.__name__ for cls in allowed_classes} def filter(self, record): frame = inspect.currentframe() while frame: if 'self' in frame.f_locals: caller_cls = frame.f_locals['self'].__class__.__name__ if caller_cls in self.allowed: return True frame = frame.f_back return False # 使用方式:给输出handler挂载过滤器,仅放行IBRobo类的日志 # stream_handler.addFilter(AllowedClassFilter([IBRobo]))
Q2:是否存在可行方案,针对选定的已导入模块配置日志过滤规则,屏蔽其冗余日志输出?
存在,这是Python标准logging模块的基础能力,实现成本极低。
Python logging的logger是按模块名做树形层级管理的,第三方模块一般都会以自身模块名作为logger名称打日志,你只需要拿到对应模块的logger实例,将其日志级别设置为高于INFO(比如直接设为CRITICAL + 1屏蔽所有级别日志),或者关闭其向上传播属性,就能完全阻断该模块的日志输出到控制台。
针对给出的业务场景,只需要加两行配置就能完全屏蔽HeavyLoggingINFO模块的冗余INFO日志,最终可运行的完整代码如下:
import logging from HeavyLoggingINFO import Client class IBRobo: def __init__(self): # 推荐业务类使用独立命名的logger self.logger = logging.getLogger("IBRobo") hlog_client = Client() hlog_client.run() def run(self): # 用专属logger打业务日志 self.logger.info('MY APP LOG STATEMENT') if __name__ == '__main__': # 第一步:优先屏蔽第三方模块的所有日志 third_party_logger = logging.getLogger("HeavyLoggingINFO") third_party_logger.setLevel(logging.CRITICAL + 1) third_party_logger.propagate = False # 第二步:配置业务类的日志输出 app_logger = logging.getLogger("IBRobo") app_logger.setLevel(logging.INFO) stream_handler = logging.StreamHandler() app_logger.addHandler(stream_handler) app_logger.propagate = False robo = IBRobo() robo.run()
运行后控制台只会打印MY APP LOG STATEMENT,不会出现任何HeavyLoggingINFO.Client产生的冗余日志。
内容的提问来源于stack exchange,提问作者Karun
相关产品推荐
相关产品推荐

