python logger - 只能运行一次

时间:2017-05-06 21:51:43

标签: python logging jupyter-notebook

我正在使用jupyter笔记本测试python记录器。

当我在新启动的内核中运行以下示例代码时,它可以工作并使用正确的内容创建日志文件。

import logging
logging.basicConfig(filename='/home/depot/wintergreen/example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')

但是,如果我尝试重新运行相同的代码,例如,文件名从example.log更改为example.log2,则没有任何反应,文件example.log2未创建。

我最终设计了这个测试,因为在我看来,当我尝试运行日志记录时,它只会在我第一次运行时运行。我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

您是对的,.basicConfig()仅使用您的kwargs一次。因为在你第一次得到处理程序logging.root.handlers后,实际上有一个处理程序,所以如果你查看source code

def basicConfig(**kwargs):
    ...
    _acquireLock()
    try:
        if len(root.handlers) == 0:
            ...
    finally:
        _releaseLock()

所以,因为你所提供的参数的len(root.handlers) != 0实际分配没有发生。

如何在不重新启动的情况下进行更改:

我提出的唯一解决方案是在不重新启动内核的情况下调用.basicConfig()来更改基本配置:

for handler in logging.root.handlers:
    logging.root.removeHandler(handler)

这将删除root logger中的所有处理程序,之后你可以设置任何你想要的东西。

答案 1 :(得分:2)

问题是basicConfig()函数只能运行一次。

根据文档:第一次运行时,它会创建一个带有默认格式化程序的StreamHandler并将其添加到根记录器"。但是,如果根记录器已经为其配置了处理程序,那么"函数第二次就不起作用了。

一种可能的解决方案是使用logging.root.removeHandler清除前一个处理程序。或者,您可以直接访问StreamHandler实例使用的开放流的 stream 属性:

>>> import logging
>>> logging.basicConfig(filename='abc.txt') # 1st call to basicConfig
>>> h = logging.root.handlers[0]            # get the handler
>>> h.stream.close()                        # close the current stream
>>> h.stream = open('def.txt', 'a')         # set-up a new stream

FWIW, basicConfig()logging模块的后期添加内容,用于常见案例的simplified short-cut API。一般来说,每当你遇到 basicConfig()的问题时,就意味着是时候使用完整的API,这样不太方便,但可以让你获得更多的控制权:

import logging

# First pass
h = logging.StreamHandler(open('abc.txt', 'a'))
h.setLevel(logging.DEBUG)
h.setFormatter(logging.Formatter('%(asctime)s | %(message)s'))
logging.root.addHandler(h)
logging.critical('The GPU is melting')

# Later passes
logging.root.removeHandler(h)
h = logging.StreamHandler(open('def.txt', 'a'))
h.setLevel(logging.DEBUG)
h.setFormatter(logging.Formatter('%(asctime)s | %(message)s'))
logging.root.addHandler(h)
logging.critical('The CPU is getting hot too')