Python类中logging模块的正确导入配置问题咨询
问题解决与代码调整
问题根源
- 控制台输出DEBUG日志:大概率是后续操作中StreamHandler的日志级别被意外修改,或是Jupyter Notebook环境下logger的Handler状态出现异常,导致原本设置为INFO级别的StreamHandler失效。
- 日志重复记录:直接移除
if not logger.handlers:会导致每次调用get_logger都添加新的Handler,多个同类型Handler同时写入日志文件,造成重复记录。
调整方案
方案一:保留单次Handler添加逻辑,修复级别异常
适合希望减少Handler创建开销,仅在首次初始化时添加Handler的场景,同时确保已有Handler的级别符合预期:
import logging from logging.handlers import TimedRotatingFileHandler _log_format = f"%(asctime)s - [%(levelname)s] - %(name)s - " \ f"(%(filename)s).%(funcName)s(%(lineno)d) - %(message)s" def get_timed_rotating_file_handler(): file_handler = TimedRotatingFileHandler("zon_logs.log", when='D', interval=30, backupCount=15, delay=False, utc=False) file_handler.setLevel(logging.DEBUG) # 记录DEBUG及以上级别到文件 file_handler.setFormatter(logging.Formatter(_log_format)) return file_handler def get_stream_handler(): stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) # 控制台输出INFO及以上级别 stream_handler.setFormatter(logging.Formatter(_log_format)) return stream_handler def get_logger(name="Admin"): logger = logging.getLogger(name) # 仅在logger未配置Handler时初始化 if not logger.handlers: logger.setLevel(logging.DEBUG) logger.addHandler(get_timed_rotating_file_handler()) logger.addHandler(get_stream_handler()) else: # 遍历已有Handler,强制修正级别,防止被意外修改 for handler in logger.handlers: if isinstance(handler, TimedRotatingFileHandler): handler.setLevel(logging.DEBUG) elif isinstance(handler, logging.StreamHandler): handler.setLevel(logging.INFO) return logger
方案二:每次获取Logger时清理旧Handler,彻底避免重复与异常
适合Jupyter Notebook这种模块可能被反复重载的环境,通过先清理同类型旧Handler再添加新的,彻底解决重复记录和级别异常问题:
import logging from logging.handlers import TimedRotatingFileHandler _log_format = f"%(asctime)s - [%(levelname)s] - %(name)s - " \ f"(%(filename)s).%(funcName)s(%(lineno)d) - %(message)s" def get_timed_rotating_file_handler(): file_handler = TimedRotatingFileHandler("zon_logs.log", when='D', interval=30, backupCount=15, delay=False, utc=False) file_handler.setLevel(logging.DEBUG) # 记录DEBUG及以上级别到文件 file_handler.setFormatter(logging.Formatter(_log_format)) return file_handler def get_stream_handler(): stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) # 控制台输出INFO及以上级别 stream_handler.setFormatter(logging.Formatter(_log_format)) return stream_handler def get_logger(name="Admin"): logger = logging.getLogger(name) logger.setLevel(logging.DEBUG) # 移除已存在的同类型Handler,避免重复记录 for handler in list(logger.handlers): if isinstance(handler, TimedRotatingFileHandler) or isinstance(handler, logging.StreamHandler): logger.removeHandler(handler) # 添加新的Handler logger.addHandler(get_timed_rotating_file_handler()) logger.addHandler(get_stream_handler()) return logger
方案说明
- 方案一通过检查并修正已有Handler的级别,解决了Jupyter环境中可能出现的级别篡改问题,同时保留了仅初始化一次Handler的逻辑,避免日志重复。
- 方案二则彻底规避了Handler重复添加的问题,代价是每次获取Logger时都会重新创建Handler,性能开销极小,日常使用可忽略。
内容的提问来源于stack exchange,提问作者Luckasino
相关产品推荐
相关产品推荐

