Python中StreamHandler的setLevel无效

4 投票
2 回答
3788 浏览
提问于 2025-04-17 09:57

我设置了日志记录,代码如下:

def setUp():

    LOG_FORMAT = '%(asctime)s %(levelname)-8s %(name)s %(message)s'
    #LOG_FORMAT = '%(asctime)s %(name)s %(message)s'

    logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)
    formatter = logging.Formatter(LOG_FORMAT)

    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    ch.setFormatter(formatter)
    logging.getLogger().addHandler(ch)

    LOG_FILENAME = 'file.log'
    fh = logging.FileHandler(LOG_FILENAME, 'w')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    logging.getLogger().addHandler(fh)

但是,控制台还是显示了 DEBUG 消息。我是不是漏掉了什么?

需要注意的是,把 fh 的级别设置为 ERROR 是可以正常工作的。

2 个回答

2

来自Python文档关于 logging.basicConfig 的内容:

这个方法用于对日志系统进行基本配置,它会创建一个默认格式的StreamHandler,并将其添加到根日志记录器(root logger)中。

当你把根日志记录器的调试级别设置为 logging.DEBUG,并且没有关闭向根日志记录器转发消息的功能时,你的DEBUG消息就会通过这个由 basicConfig 创建的StreamHandler被记录下来。

2

我觉得你需要去掉对 logging.basicConfig 的调用。这个函数会添加一个新的 logging.StreamHandler,可能正是这个处理器在打印你不想看到的消息。

你可以查看根日志记录器的 handlers 属性(这是一个包含所有正在使用的处理器的列表),来检查一下有多少个 logging.StreamHandler。另外,可能因为有两个 logging.StreamHandler,所以级别为 logging.ERROR 的消息会被打印两次。

我的最终建议是,如果你打算在代码中明确配置处理器,就尽量不要使用 logging.basicConfig

补充一下,logging.BasicConfig 的源代码如下:

if len(root.handlers) == 0:
    filename = kwargs.get("filename")
    if filename:
        mode = kwargs.get("filemode", 'a')
        hdlr = FileHandler(filename, mode)
    else:
        stream = kwargs.get("stream")
        hdlr = StreamHandler(stream)
    fs = kwargs.get("format", BASIC_FORMAT)
    dfs = kwargs.get("datefmt", None)
    fmt = Formatter(fs, dfs)
    hdlr.setFormatter(fmt)
    root.addHandler(hdlr)
    level = kwargs.get("level")
    if level is not None:
        root.setLevel(level)

在这里你可以看到,除非传入 filename,否则会创建一个 logging.StreamHandler

撰写回答