当前位置: 首页 > 编程笔记 >

Python中logging实例讲解

壤驷宏才
2023-03-14
本文向大家介绍Python中logging实例讲解,包括了Python中logging实例讲解的使用技巧和注意事项,需要的朋友参考一下

logging 的基本用法网上很多,这里就不介绍了。在引入正文之前,先来看一个需求:

假设需要将某功能封装成类库供他人使用,如何处理类库中的日志?

数年前在一个 C# 开发的项目中,我用了这样的方法:定义一个 logging 基类,所有需要用到日志的类都继承这个基类,这个基类中定义一个 LogHandler 事件,该事件用于实现具体的记录日志动作,同时可以通过将类 A 的 LogHandler 委托挂到类 B 的 LogHandler 上,实现将两个类的日志信息添加到一起。

自从看了 python 中 logging 的实现方式,我发现我的做法真是弱爆了。

我在之前的博客 Python:logging.NullHandler 的使用 中介绍了 peewee 框架中的日志输出,简单来说就是 peewee 中定义了一个名为peewee 的 Logger 并添加了一个 NullHandler,调用者只需要为其添加具体的 Handler 就可以输出日志了,非常方便。

假设我们在主程序中也有一个 Logger,调用 peewee 后,我想将两个日志输出到同一个日志文件中去。显然将两个日志的 FileHandler 指向同一个日志文件是不可取的,存在并发抢占文件的风险。当然我们也可以将主程序中的 Logger 名字定为 peewee,但这不仅太 low 了,而且如果再调用一个库,其中也封装好了一个 Logger,就不好处理了。

树桩结构的 Logger

Logger 对象被设计为一个树形结构,它有一个 parent 属性。logging 中定义了一个名为 root 的 Logger 作为所有 Logger 的根节点,root 的 parent 属性为 None。root 是全局的。

当调用

logging.getLogger(name=None)

得到一个 Logger 对象的时候,如果 name 为 None,则返回根节点 root。如果 name 中含有 .,比如 name = 'a.b',这时如果已经存在了名为 a 的 Logger,则 a.b 为 a 的子节点,如果不存在名为 a 的 Logger,则 a.b 为 root 的子节点。

child logger 在完成对日志消息的处理后,默认会将日志消息传递给与它的 parent logger。因此,我们不必为一个应用程序中使用的所有 Logger 定义和配置 handlers,只需要为一个顶层的 Logger 配置 handlers,然后按照需要创建 child loggers 就可足够了。我们可以通过设置 Logger 的 propagate 属性设置为 False 来关闭这种传递机制。

什么意思呢,我们来看代码:

import logging
logA = logging.getLogger('a')
logA.setLevel(logging.DEBUG)
logA.addHandler(logging.StreamHandler())
logB = logging.getLogger('a.b')
logB.addHandler(logging.StreamHandler())

输出结果:

Logger A
Logger B
Logger B

之所以 Logger B 被输出了 2 次,是因为 logB 是 logA 的子节点,并且 logB 中也定义了 Handler,所以 logB 的 Handler 输出了一次,logA 的 Handler 也输出了一次,就 2 次了。如果想只输出一次,可以删掉 logB 中的 Handler。当然,这也是有用处的,尤其是当你手头没有日志管理工具的时候。例如,主程序中需要输出所有的日志,以便了解程序整体的运行顺序,而某模块的日志,你想单独输出一份,以便清晰了解模块中的报错或者是执行顺序。

之前 peewee 的例子也就很容易解决了,只需要将 peewee 日志的 parent 属性设置为主程序的日志就可以了。

结语

其实这是一个比较容易说明的问题,完全没必要写这么多。我并不想跟大家分享 python 中的 logging 是怎么用的,而是想和大家分享 logging 如此实现的一种思想,因为我遇到过这个问题,也设计了解决方案,然后被完爆了。

 类似资料:
  • 本文向大家介绍python中numpy.empty()函数实例讲解,包括了python中numpy.empty()函数实例讲解的使用技巧和注意事项,需要的朋友参考一下 在使用python编程的过程中,想要快速的创建ndarray数组,可以使用numpy.empty()函数。numpy.empty()函数所创建的数组内所有元素均为空,没有实际意义,所以它也是创建数组最快的方法。本文介绍python中

  • 本文向大家介绍Python中logging模块的用法实例,包括了Python中logging模块的用法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了logging模块的用法实例,分享给大家供大家参考。具体方法如下: 程序运行结果如下: 希望本文所述对大家的Python程序设计有所帮助。

  • 本文向大家介绍python中的多重继承实例讲解,包括了python中的多重继承实例讲解的使用技巧和注意事项,需要的朋友参考一下 python和C++一样,支持多继承。概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性。 对经典类和新式类来说,属性的查找顺序是不同的。现在我们分别看一下经典类和新式类两种不同的表现:

  • 本文向大家介绍实例讲解Python中的私有属性,包括了实例讲解Python中的私有属性的使用技巧和注意事项,需要的朋友参考一下 在Python中可以通过在属性变量名前加上双下划线定义属性为私有属性,如例子: 执行输出: 访问私有属性__name时居然提示找不到属性成员而不是提示权限之类的,于是当你这么写却不报错: 执行结果: 1 lisi 在Python中就算继承也不能相互访问私有变量,如: 执行

  • 本文向大家介绍Python中用xlwt制作表格实例讲解,包括了Python中用xlwt制作表格实例讲解的使用技巧和注意事项,需要的朋友参考一下 在Python中,我们也可以用xlwt来制作excel表格,是不是很神奇,接下来一起学习吧。 举例: 单元格样式控制: 背景色对照: 到此这篇关于Python中用xlwt制作表格实例讲解的文章就介绍到这了,更多相关Python中如何用xlwt制作表格内容请

  • 本文向大家介绍实例代码讲解Python 线程池,包括了实例代码讲解Python 线程池的使用技巧和注意事项,需要的朋友参考一下 大家都知道当任务过多,任务量过大时如果想提高效率的一个最简单的方法就是用多线程去处理,比如爬取上万个网页中的特定数据,以及将爬取数据和清洗数据的工作交给不同的线程去处理,也就是生产者消费者模式,都是典型的多线程使用场景。 那是不是意味着线程数量越多,程序的执行效率就越快呢