Python日志为什么输出两次?

Jam*_*Lin 6 python

我有以下代码设置记录器:

import logging

logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)
log = logging.getLogger()
handler = logging.StreamHandler(sys.stdout)
log.addHandler(handler)

log.info('abc')
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我得到如下输出:

2020-06-10 13:32:16,245 INFO: abc
abc
Run Code Online (Sandbox Code Playgroud)

我认为第一个是控制台输出?我如何摆脱重复的?

更新

谢谢大家的答案,现在我知道为什么我会得到重复,我这样做的原因是因为默认流处理程序不会输出到标准输出,所以我用谷歌搜索并看到有人添加了标准输出处理程序,因此我得到了 2 个流处理程序(控制台和标准输出)。

我现在再次阅读了关于 的文档basicConfig(),我已经找到了实现我想要的最简单的方法:

2020-06-10 13:32:16,245 INFO: abc
abc
Run Code Online (Sandbox Code Playgroud)

wim*_*wim 1

此调用logging.basicConfig将已经添加一个流处理程序(到 stderr),因此没有理由手动添加另一个流处理程序。这样做会导致重复输出到终端,在您的情况下,每个日志事件都会在stderr 和 stdout上打印。

如果您希望流处理程序为 stdout 而不是 stderr,只需basicConfig通过指定streamhandlers关键字(文档)相应地调整调用。

您还可以清理其他两件事:使用绑定到模块上下文的记录器而不是直接使用根记录器,并避免在导入时__name__配置模块。logging如果您在导入时过于急切地配置日志系统,那么用户(和测试套件)将无法再以不同的方式对其进行配置。

import logging

# create your logger as module level global
log = logging.getLogger(__name__)

def main():
    # configure logging at entry point (so it is not configured at *import* time)
    fmt = '%(asctime)s %(levelname)s: %(message)s'
    logging.basicConfig(format=fmt, level=logging.INFO)  # streamhandler to stderr
    log.info('abc')


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)