我看到一种我无法解释的行为......这是我的简化设置:
模块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
,我就看不到日志了。
这是什么,我甚至不能?...
答案 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')
我们现在通过handler
以formatter
指定的格式将记录打印到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}}不会打印记录 - 它尚未为此配置,但它会将记录进一步传递给知道如何打印记录的根记录器。