Python中无法为两个日志处理器设置不同级别?如何正确配置?
Python Logging 双处理器级别问题解答
问题1:为啥FileHandler和StreamHandler的日志级别表现得一模一样?
这事儿的核心原因是你没给自定义的logger设置级别,导致日志过滤逻辑跑偏了。
咱们先理清楚Python logging的工作流程:一条日志要被输出,得闯两道关:
- Logger关卡:日志级别得大于等于logger的有效级别,才能被logger传给它的各个handler,同时还会根据
propagate属性传给父logger(默认是root logger)。 - Handler关卡:每个handler再单独检查日志级别,只有符合自己设置的级别才会输出。
你之前的代码里没给logger设级别,那它就会继承父logger的级别(root默认是WARNING)。但这里出问题的点在于:
- 默认情况下,logger的
propagate是开着的(True),也就是说,只要过了logger的关卡,日志还会传给root的handler。 - 如果你之前用过
logging.basicConfig()之类的操作改了root的级别(比如设成了INFO),或者root已经有了自己的handler,那INFO级别的日志就会被root的handler输出——你可能误以为是自己写的FileHandler和StreamHandler都在输出INFO,但其实可能是root的handler在搞事情。 - 另外,如果你的logger因为没设级别导致有效级别低于INFO(比如继承了root的INFO级别),那它会把INFO日志传给所有handler,要是你的FileHandler级别不小心设成了INFO(哪怕你以为是WARNING),那自然文件里也会有INFO日志。
问题2:怎么正确给两个日志处理器设置不同级别?
要实现控制台打INFO及以上,文件只写WARNING及以上,你得把这几点做好:
- 给自定义logger设好级别:这是重中之重!你得把logger的级别设成两个handler里最低的那个(这里就是INFO),这样所有INFO及以上的日志都能传到handler手里,再让各自的handler去过滤。
- 分别给两个handler设对应级别:控制台处理器设INFO,文件处理器设WARNING。
- 可选:关掉logger的propagate:避免日志被root的handler重复输出,省得日志打两遍。
修改后的代码是这样的:
import logging def initialize_logger(): logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # 必须加!确保INFO及以上日志能到handler手里 logger.propagate = False # 可选,防止root logger重复输出 # 文件处理器:只处理WARNING及以上 fh = logging.FileHandler('error.log') fh.setLevel(logging.WARNING) # 控制台处理器:处理INFO及以上 ch = logging.StreamHandler() ch.setLevel(logging.INFO) # 统一格式 formatter = logging.Formatter('%(name)s - %(message)s') ch.setFormatter(formatter) fh.setFormatter(formatter) # 把处理器加给logger logger.addHandler(ch) logger.addHandler(fh) return logger logger = initialize_logger() # 测试下效果 logger.info("这条INFO日志只会在控制台显示") logger.warning("这条WARNING日志控制台和文件都会有") logger.error("这条ERROR日志也是两边都有")
这么改完之后:
- logger的级别是INFO,所以INFO及以上的日志都会传给两个handler
- StreamHandler只留INFO及以上,所以控制台能看到所有INFO、WARNING、ERROR
- FileHandler只留WARNING及以上,所以文件里只有WARNING和ERROR
- 关掉
propagate就不会让root logger再插一脚重复输出了
内容的提问来源于stack exchange,提问作者sudonym
相关产品推荐
相关产品推荐

