Python logging多Handler场景下单独修改StreamHandler日志级别问题
解决方案
核心原理
Python logging模块采用分层过滤规则:
- 日志首先会经过Logger本身的级别校验,低于Logger设置级别的日志会直接被丢弃,不会向下传递到任何Handler
- 所有通过Logger校验的日志,会逐个发送给Logger绑定的每个Handler,每个Handler会独立执行自己的级别校验,符合级别的才会输出
你要满足「FileHandler固定收DEBUG日志、StreamHandler级别可动态调整」的需求,只需要把Logger本身的级别固定为DEBUG(覆盖所有Handler需要的最低级别),单独修改StreamHandler的级别即可,不需要修改Logger全局级别。
logUtils.py 自定义Logger实现
import logging class MyLogger(logging.Logger): def __init__(self, name, log_file_path="app.log"): # Logger全局级别固定设为DEBUG,保证所有需要的日志都能传递到Handler super().__init__(name, level=logging.DEBUG) # 避免重复添加Handler导致日志重复打印 if self.handlers: return # 配置固定DEBUG级别的FileHandler file_handler = logging.FileHandler(log_file_path, encoding="utf-8") file_handler.setLevel(logging.DEBUG) file_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") file_handler.setFormatter(file_formatter) self.addHandler(file_handler) # 配置默认INFO级别的StreamHandler,存为实例属性方便后续调整 self.stream_handler = logging.StreamHandler() self.stream_handler.setLevel(logging.INFO) stream_formatter = logging.Formatter("%(levelname)s: %(message)s") self.stream_handler.setFormatter(stream_formatter) self.addHandler(self.stream_handler) # 对外暴露修改StreamHandler级别的方法 def set_stream_level(self, level): self.stream_handler.setLevel(level) # 注册自定义Logger类,后续调用logging.getLogger会返回MyLogger实例 logging.setLoggerClass(MyLogger)
主脚本调用示例
import argparse import logging import logUtils # 导入自定义模块自动完成Logger类注册 if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-v", "--verbose", action="store_true", help="开启调试模式,控制台输出DEBUG级别日志") args = parser.parse_args() # 获取自定义Logger实例 logger = logging.getLogger("my_app") # 仅调整StreamHandler级别,不影响Logger全局和FileHandler的配置 if args.verbose: logger.set_stream_level(logging.DEBUG) # 测试日志 logger.debug("调试日志:verbose模式下才会在控制台显示,始终会写入文件") logger.info("普通日志:控制台和文件默认都会显示")
注意事项
- 不需要对外暴露StreamHandler本身,仅通过
set_stream_level方法调整级别即可,符合封装原则 - 自定义Logger的
__init__中添加了Handler存在性判断,避免多模块重复导入时重复添加Handler,导致日志重复打印 - 如果后续需要调整FileHandler的级别,也可以参照StreamHandler的实现,增加对应的调整方法
内容的提问来源于stack exchange,提问作者Limone
相关产品推荐
相关产品推荐

