Python 3.6.4+PyCharm 2017.3日志重复输出问题求助
嘿,我来帮你拆解这个问题:你配置了日志让文件输出DEBUG级内容、控制台仅输出ERROR级内容,但控制台却额外冒出了无格式的DEBUG/INFO日志,文件输出倒是完全符合预期。排查后没发现多余的StreamHandler,这其实是Python logging模块的根Logger默认机制导致的代码问题,和PyCharm配置无关。
问题根源
当你创建自定义Logger(logging.getLogger(__name__))时,Logger默认有个propagate属性是True——意思是它会把处理过的日志向上传播给父Logger(最终到根Logger)。
而根Logger在你第一次输出日志时,会自动生成一个默认的StreamHandler,这个Handler没有设置格式化规则,且级别为NOTSET(会接收所有传播过来的日志)。所以你的自定义Logger处理完DEBUG/INFO/ERROR日志后,除了交给自己配置的文件和控制台Handler,还会把这些日志传给根Logger,根Logger的默认Handler就把它们以无格式的样子输出到控制台了。
你之前查logging.getLogger().handlers得到空列表,是因为你在日志输出前查询的——根Logger的默认Handler是第一次日志输出时才会创建,你可以在LOGGER.error("Test ERROR message")之前加一行打印验证:
print("Root Logger handlers:", logging.getLogger().handlers)
修复方案
只需要给你的自定义Logger加一行,关闭日志传播即可:
LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) LOGGER.propagate = False # 关键:阻止日志向上传播到根Logger # 以下是你原有的配置,无需修改 fh = logging.FileHandler('clsfr.log') fh.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.ERROR) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) fh.setFormatter(formatter) LOGGER.addHandler(ch) LOGGER.addHandler(fh)
加上这行后,自定义Logger的日志就只会交给你自己配置的两个Handler处理,不会再传给根Logger,控制台就只会输出你格式化后的ERROR日志了。
额外验证
修改后再运行代码,控制台只会出现那一行格式化的ERROR日志,那些DEBUG:__main__:...的无格式日志会完全消失,和你预期的一致。
内容的提问来源于stack exchange,提问作者Chanonry

