引言

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

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

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

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

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


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

树桩结构的 Logger

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

当调用

logging.getLogger(name=None)

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

child logger 在完成对日志消息的处理后,默认会将日志消息传递给与它的 parent logger。因此,我们不必为一个应用程序中使用的所有 Logger 定义和配置 handlers,只需要为一个顶层的 Logger 配置 handlers,然后按照需要创建 child loggers 就可足够了。我们可以通过设置 Loggerpropagate 属性设置为 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 次,是因为 logBlogA 的子节点,并且 logB 中也定义了 Handler,所以 logBHandler 输出了一次,logAHandler 也输出了一次,就 2 次了。如果想只输出一次,可以删掉 logB 中的 Handler。当然,这也是有用处的,尤其是当你手头没有日志管理工具的时候。例如,主程序中需要输出所有的日志,以便了解程序整体的运行顺序,而某模块的日志,你想单独输出一份,以便清晰了解模块中的报错或者是执行顺序。

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

结语

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


我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1ik0uj4dod1ui

Python:logging 的巧妙设计的更多相关文章

  1. Python logging 模块和使用经验

    记录下常用的一些东西,每次用总是查文档有点小麻烦. py2.7 日志应该是生产应用的重要生命线,谁都不应该掉以轻心 有益原则 级别分离 日志系统通常有下面几种级别,看情况是使用 FATAL - 导致程 ...

  2. python logging详解及自动添加上下文信息

    之前写过一篇文章日志的艺术(The art of logging),提到了输出日志的时候记录上下文信息的重要性,我认为上下文信息包括: when:log事件发生的时间 where:log事件发生在哪个 ...

  3. python logging模块,升级print调试到logging。

    简介: 我们在写python程序的时候,很多时候都有bug,都是自己写的,自己造的孽,又的时候报错又是一堆,不知道是那部分出错了. 我这初学者水平,就是打print,看哪部分执行了,哪部分没执行,由此 ...

  4. 0x01 Python logging模块

    目录 Python logging 模块 前言 logging模块提供的特性 logging模块的设计过程 logger的继承 logger在逻辑上的继承结构 logging.basicConfig( ...

  5. python logging模块可能会令人困惑的地方

    python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...

  6. python logging 配置

    python logging 配置 在python中,logging由logger,handler,filter,formater四个部分组成,logger是提供我们记录日志的方法:handler是让 ...

  7. Python LOGGING使用方法

    Python LOGGING使用方法 1. 简介 使用场景 场景 适合使用的方法 在终端输出程序或脚本的使用方法 print 报告一个事件的发生(例如状态的修改) logging.info()或log ...

  8. python logging 日志轮转文件不删除问题

    前言 最近在维护项目的python项目代码,项目使用了 python 的日志模块 logging, 设定了保存的日志数目, 不过没有生效,还要通过contab定时清理数据. 分析 项目使用了 logg ...

  9. python logging模块使用

    近来再弄一个小项目,已经到收尾阶段了.希望加入写log机制来增加程序出错后的判断分析.尝试使用了python logging模块. #-*- coding:utf-8 -*- import loggi ...

随机推荐

  1. 用一张表里的记录更新自己(或另一张表)里的记录(exists使用)

    update jqhdzt set shid=(select shid from v_plat_userjqinfo t where jqhdzt.jqbh=t.JQBH and jqhdzt.shi ...

  2. Python3实现ICMP远控后门(上)_补充篇

    ICMP后门(上)补充篇 前言 在上一篇文章Python3实现ICMP远控后门(上)中,我简要讲解了ICMP协议,以及实现了一个简单的ping功能,在文章发表之后,后台很多朋友留言,说对校验和的计算不 ...

  3. JAVA之单源最短路径(Single Source Shortest Path,SSSP问题)dijkstra算法求解

    题目简介:给定一个带权有向图,再给定图中一个顶点(源点),求该点到其他所有点的最短距离,称为单源最短路径问题. 如下图,求点1到其他各点的最短距离 准备工作:以下为该题所需要用到的数据 int N; ...

  4. Zookeeper学习

    http://www.cnblogs.com/caosiyang/archive/2012/11/09/2763190.html   http://www.cnblogs.com/haippy/tag ...

  5. WPF MVVM UI分离之《交互与数据分离》

    在我们使用WPF过程中,不可避免并且超级喜欢使用MVVM框架. 那么,使用MVVM的出发点是视觉与业务逻辑分离,即UI与数据分离 诸如下面的问题: 删除操作,假如需要先执行一部分数据的处理,然后删除界 ...

  6. Linux内存使用情况以及内存泄露分析之工具与方法

    <Linux C/C++ Memory Leak Detection Tool> 1. 内存使用情况分析 1.1 系统总内存分析 通过cat /proc/meminfo,可用的物理内存=M ...

  7. 通过VirtualBox安装Linux系统(CentOS7)

    本文目的:创建虚拟系统.在windows系统中通过虚拟工具VirtualBox创建一个虚拟系统CentOS. 备注:(1)版本如下:VirtualBox-5.2.12-122591-Win 和Cent ...

  8. aliyun TableStore相关操作汇总

    总结:这个东西本身可能技术还不成熟,使用的人少,有问题很验证解决 遇到的问题:(1)没有一个GUI工具,使用门槛高(2)查询的GetRange不方便,把查询出来的数据使用System.out.prin ...

  9. AES在线加密解密-附AES128,192,256,CBC,CFB,ECB,OFB,PCBC各种加密解密源码

    一.AES在线加密解密:AES 128/192/256位CBC/CFB/ECB/OFB/PCBC在线加密解密|在线工具|在线助手|在线生成|在线制作 http://www.it399.com/aes ...

  10. Dubbo中SPI扩展机制解析

    dubbo的SPI机制类似与Java的SPI,Java的SPI会一次性的实例化所有扩展点的实现,有点显得浪费资源. dubbo的扩展机制可以方便的获取某一个想要的扩展实现,每个实现都有自己的name, ...