Python中logging实例讲解


Posted in Python onJanuary 17, 2019

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

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

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

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

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

Python中logging实例讲解

假设我们在主程序中也有一个 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 相关文章推荐
python实现的登陆Discuz!论坛通用代码分享
Jul 11 Python
python中for语句简单遍历数据的方法
May 07 Python
Python pickle模块用法实例分析
May 27 Python
在Python的Django框架下使用django-tagging的教程
May 30 Python
Python3中简单的文件操作及两个简单小实例分享
Jun 18 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 Python
详解Python列表赋值复制深拷贝及5种浅拷贝
May 15 Python
python使用递归的方式建立二叉树
Jul 03 Python
Python二维码生成识别实例详解
Jul 16 Python
Python解析json时提示“string indices must be integers”问题解决方法
Jul 31 Python
django+tornado实现实时查看远程日志的方法
Aug 12 Python
python3 实现mysql数据库连接池的示例代码
Apr 17 Python
python矩阵/字典实现最短路径算法
Jan 17 #Python
python实现Dijkstra静态寻路算法
Jan 17 #Python
解决在Python编辑器pycharm中程序run正常debug错误的问题
Jan 17 #Python
python实现dijkstra最短路由算法
Jan 17 #Python
Pycharm 设置默认头的图文教程
Jan 17 #Python
python实现狄克斯特拉算法
Jan 17 #Python
在PyCharm下使用 ipython 交互式编程的方法
Jan 17 #Python
You might like
PHP中static关键字原理的学习研究分析
2011/07/18 PHP
解析func_num_args与func_get_args函数的使用
2013/06/24 PHP
JQuery中each()的使用方法说明
2010/08/19 Javascript
js实现拖拽 闭包函数详细介绍
2012/11/25 Javascript
子页向父页传值示例
2013/11/27 Javascript
jQuery的$.proxy()应用示例介绍
2014/04/03 Javascript
js简单实现竖向tab选项卡的方法
2015/05/04 Javascript
浅谈js多维数组和hash数组定义和使用
2016/07/27 Javascript
Angularjs 自定义服务的三种方式(推荐)
2016/08/02 Javascript
JS百度地图搜索悬浮窗功能
2017/01/12 Javascript
深入nodejs中流(stream)的理解
2017/03/27 NodeJs
js canvas实现擦除效果示例代码
2017/04/26 Javascript
js实现城市级联菜单的2种方法
2017/06/23 Javascript
JS库之Three.js 简易入门教程(详解之一)
2017/09/13 Javascript
详解Node全局变量global模块
2017/09/28 Javascript
Vue2 模板template的四种写法总结
2018/02/23 Javascript
vue组件详解之使用slot分发内容
2018/04/09 Javascript
简单了解小程序+node梳理登陆流程
2019/06/24 Javascript
Vue Extends 扩展选项用法完整实例
2019/09/17 Javascript
js实现GIF动图分解成多帧图片上传
2019/10/24 Javascript
Vue computed 计算属性代码实例
2020/04/22 Javascript
Linux系统(CentOS)下python2.7.10安装
2018/09/26 Python
在Pandas中处理NaN值的方法
2019/06/25 Python
python logging日志模块原理及操作解析
2019/10/12 Python
python 实现dict转json并保存文件
2019/12/05 Python
python shell命令行中import多层目录下的模块操作
2020/03/09 Python
python七种方法判断字符串是否包含子串
2020/08/18 Python
手摸手教你用canvas实现给图片添加平铺水印的实现
2019/08/20 HTML / CSS
丝芙兰波兰:Sephora.pl
2018/03/25 全球购物
写自荐信的注意事项
2014/03/09 职场文书
学生会感恩节活动方案
2014/10/11 职场文书
专职安全员岗位职责
2015/04/11 职场文书
2016年五一促销广告语
2016/01/28 职场文书
Go语言中break label与goto label的区别
2021/04/28 Golang
浅谈MySQL函数
2021/10/05 MySQL
关于JS中的作用域中的问题思考分享
2022/04/06 Javascript