启用模块的记录器

时间:2017-10-22 08:40:28

标签: python logging

我看到一种我无法解释的行为......这是我的简化设置:

模块x

import logging

logger = logging.getLogger('x')

def test_debugging():
    logger.debug('Debugging')

测试模块x

import logging
import unittest

from x import test_debugging


class TestX(unittest.TestCase):

    def test_test_debugging(self):
        test_debugging()


if __name__ == '__main__':
    logger = logging.getLogger('x')
    logger.setLevel(logging.DEBUG)
    # logging.debug('another test')
    unittest.main()

如果我取消注释logging.debug('another test')行,我还可以从x查看日志。请注意,这不是拼写错误,我在debug上调用logging,而不是在模块logger上调用x。如果我在debug上拨打logger,我就看不到日志了。

这是什么,我甚至不能?...

1 个答案:

答案 0 :(得分:2)

在您的设置中,您实际上并未配置日志记录。虽然配置可能相当复杂,但只需在示例中设置日志级别即可:

if __name__ == '__main__':
    # note I configured logging, setting e.g. the level globally
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger('x')
    logger.setLevel(logging.DEBUG)
    unittest.main()

这将创建一个带有预定义输出格式的简单StreamHandler,将所有日志记录打印到stdout。我建议您快速查看relevant docs以获取更多信息。

为什么它适用于logging.debug电话?由于logging.{info,debug,warn,error}函数都在内部调用logging.basicConfig,因此一旦调用logging.debug,就会隐式配置日志记录。

编辑:让我们快速了解一下logging.{info,debug,error,warning}函数的实际含义。我们来看下面的片段:

import logging
logger = logging.getLogger('mylogger')
logger.warning('hello world')

如果您运行代码段,则不会打印hello world(这是正确的!)。为什么不?这是因为你没有真正指定应该如何处理日志记录 - 它们应该打印到stdout,还是打印到文件,或者可能发送到某个服务器,然后通过电子邮件发送给收件人?记录器mylogger 接收日志记录hello world,但它还不知道如何处理它。因此,要实际打印记录,让我们为记录器做一些配置:

import logging
logger = logging.getLogger('mylogger')
formatter = logging.Formatter('Logger received message %(message)s at time %(asctime)s')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.warning('hello world')

我们现在通过handlerformatter指定的格式将记录打印到stdout,附加了{em>处理记录的hello world。现在记录StreamHandler将打印到标准输出。我们可以附加更多的处理程序,并且每个处理程序都会处理记录。示例:尝试附加另一个logging,您会注意到该记录现在打印了两次。

那么,现在logging函数有什么用?如果你有一个简单的程序,只有一个记录器可以打印消息,那么你可以使用方便的import logging logging.warning('hello world') 函数替换手动配置:

StreamHandler

这将配置根记录器通过向其添加hello world和一些默认格式化程序来将消息打印到stdout,因此您不必自己配置它。之后,它将告诉根记录器处理记录logging.basicConfig() 。仅仅是一种便利,仅此而已。如果要显式触发根记录器的此基本配置,请发出

    logging.basicConfig(level=logging.DEBUG)

有或没有其他配置参数。

现在,让我们再次浏览我的第一个代码段:

DEBUG

在此行之后,根记录器将打印所有级别为 logger = logging.getLogger('x') logger.setLevel(logging.DEBUG) 及更高级别的日志记录到命令行。

x

我们没有明确配置此记录器,为什么记录仍在打印?这是因为默认情况下,任何记录器都会将日志记录传播到根记录器。因此记录器{{1}}不会打印记录 - 它尚未为此配置,但它会将记录进一步传递给知道如何打印记录的根记录器。