首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python:logging 的巧妙设计

引言

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

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

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

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

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

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

树桩结构的 Logger

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

当调用

得到一个 对象的时候,如果 为 ,则返回根节点 。如果 中含有 ,比如 ,这时如果已经存在了名为 的 ,则 为 的子节点,如果不存在名为 的 ,则 为 的子节点。

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

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

输出结果:

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

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

结语

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

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190117G09D0M00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券