关于Python日志系统的几点建议
admin
2023-07-31 01:43:30
0

Python日志系统非常丰富。添加结构化或非结构化日志输出到python代码,写到文件,输出到控制台,发送到系统日志,或者自定义输出格式都很容易。

我们正在重新检查mozharness中日志的工作机制,希望提取代码能更容易,并减少掺合模式的使用。

下面是一些在python日志中真正帮到我们的建议和技巧:

可以有多个logger

好吧,对一个给定名称确实只会有一个logger。特殊的“根”logger没有名称。对相同名称多次调用getLogger(name)会返回相同的logger对象。这个特性很重要,你不用在代码中显式将logger对象传来传去。你可以通过名称来获取它们。日志模块维护了一个全局日志对象注册表。

你可以使用多个logger对象,每个只限定于其特定模块,甚至类或实例。

每个logger都有一个名称,通常是logger所处模块的名称。你能在Python模块中看到的通用模式大概这样:

123 # in module foo.pyimport logginglog = logging.getLogger(__name__)

这段代码没错是因为foo.py中,__name__等于”foo”。所以在此模块中,log对象只会用于这个模块。

logger可分级的

名称空间中的logger名称使用“.”来分层。这意味着如果你有foo.barfoo.baz两个logger,你可以操作foo,这样它的两个子logger都会起作用。尤其是,你可以设置foo的日志等级来显示或忽略两个子模块的调试消息。

123 # 我们为所有的foo模块启用全部调试日志输出import logginglogging.getLogger(\’foo\’).setLevel(logging.DEBUG)

日志消息类似事件,会在层次结构中流动

假设我们有个模块foo.bar:

12345 import logginglog = logging.getLogger(__name__)  # __name__ is \”foo.bar\” here def make_widget():    log.debug(\”made a widget!\”)

当我们调用make_widget()时,代码生成了一个调试日志消息。层次结构中的每个logger都有机会将这个消息输出、忽略、传递给父级。

日志默认并没有配置其等级(或设置为NOTSET))。这意味着logger只会把消息传递给父级,然后不断重复这个步骤,一直到根logger。

所以如果foo.barlogger没有指定等级,消息将继续传递到foologger。如果foologger没有指定等级,消息将会传递给根logger。

这就是为什么你通常需要在根logger上配置日志输出的原因;它通常会输出全部消息!!!这太常见了,所以有个专门的方法来配置根logger:logging.basicConfig()

这也允许我们根据消息的来源使用混合等级的日志输出:

1234567891011 import logging # 为所有的foo模块启动调试日志输出logging.getLogger(\”foo\”).setLevel(logging.DEBUG) # 配置根logger只打印INFO消息,并输出到控制台# (默认值)logging.basicConfig(level=logging.INFO) # 将会输出调试消息logging.getLogger(\”foo.bar\”).debug(\”ohai!\”)

如果注释掉setLevel(logging.DEBUG),你将不会看到任何消息。

exc_info是最棒的

所有的内建日志调用都支持exc_info关键字,如果它不是false,当前异常信息将会附加到日志消息中,比如:

123456789 import logginglogging.basicConfig(level=logging.INFO) log = logging.getLogger(__name__) try:    assert Falseexcept AssertionError:    log.info(\”surprise! got an exception!\”, exc_info=True)

log.exception()是个特例,等价于log.error(..., exc_info=True)

Python 3.2引入了一个新的关键字stack_info,将会输出当前栈到当前代码。当你想知道如何运行到代码的某处时,非常方便,即使没有异常发生也可以。

“找不到处理函数…”

你很可能遇到过这个消息,尤其是使用第三方模块时。这个错误的意思是,你没有配置任何日志处理函数,但是某处尝试打印日志消息。这个消息沿着层次结构向上传递,直到在结构链的顶处失败(也许我需要一个更好的比喻)。

123 import logginglog = logging.getLogger()log.error(\”no log for you!\”)

输出:

1 No handlers could be found for logger \”root\”

这里可以做两件事:

1.在模块中使用basicConfig()或类似的方法配置日志

2.库作者应该在模块顶层添加一个NullHandler 来防止这种情况发生。看下这里的指南和这篇博客来了解更多信息。

更多?

我极力推荐你读下日志文档和指南,它们提供了更多有用信息(写的也很好!)。你也可以通过定制自己的日志处理器来做更多事情,不同的输出格式、一次输出到多个位置等。玩得高兴!

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...
python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...