如何配置root logger与自定义logger避免日志重复输出
问题
我想要单独配置root logger和项目的自定义logger,当前的日志配置如下:
import sys import logging import logging.config logging.config.dictConfig( { "version": 1, "root": { "handlers": ["stdout"], "level": "WARNING", }, "loggers": { "my_project_name": { "handlers": ["stdout"], "level": "DEBUG", } }, "handlers": { "stdout": { "formatter": "fancy" if sys.stdout.isatty() else "normal", "class": "logging.StreamHandler", "level": "DEBUG", }, }, "formatters": { "normal": { "format": "%(asctime)s [%(levelname)s] (%(name)s): %(msg)s", "datefmt": "%Y-%m-%d %H:%M:%S.%f", }, "fancy": { "format": "TODO", "datefmt": "%Y-%m-%d %H:%M:%S.%f", } }, } )
需求是root logger记录所有logger的WARNING及以上级别日志,同时单独控制项目内所有logger的日志级别。但当前配置会导致项目日志被自定义logger和root logger同时处理,终端输出两次,求解决方法。
解决方案
问题出在Python日志系统的传播机制:自定义logger默认会把日志消息向上传播给父级logger(包括root),所以同一条日志会被自定义logger和root各自的handler处理,导致重复输出。
解决方法很简单,给项目自定义logger添加"propagate": false配置,阻止日志向上传播:
修改后的配置如下:
import sys import logging import logging.config logging.config.dictConfig( { "version": 1, "root": { "handlers": ["stdout"], "level": "WARNING", }, "loggers": { "my_project_name": { "handlers": ["stdout"], "level": "DEBUG", "propagate": False # 新增这一行,阻止日志向上传播 } }, "handlers": { "stdout": { "formatter": "fancy" if sys.stdout.isatty() else "normal", "class": "logging.StreamHandler", "level": "DEBUG", }, }, "formatters": { "normal": { "format": "%(asctime)s [%(levelname)s] (%(name)s): %(msg)s", "datefmt": "%Y-%m-%d %H:%M:%S.%f", }, "fancy": { "format": "TODO", "datefmt": "%Y-%m-%d %H:%M:%S.%f", } }, } )
这样配置后:
- 项目内
my_project_name下的所有logger,DEBUG及以上级别日志会被自己的handler处理,且不会传给root,避免重复输出 - root logger依然会捕获其他第三方logger(比如requests、urllib等)的WARNING及以上级别日志,满足“记录所有logger的WARNING及以上”的需求
- 你可以通过修改
my_project_name的level字段,单独控制项目内日志的输出级别,不影响root和其他logger的配置
内容的提问来源于stack exchange,提问作者Hubro
相关产品推荐
相关产品推荐

