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错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
Aug 22 Python
Python中实现两个字典(dict)合并的方法
Sep 23 Python
在Python3中初学者应会的一些基本的提升效率的小技巧
Mar 31 Python
用Python制作简单的钢琴程序的教程
Apr 01 Python
基础的十进制按位运算总结与在Python中的计算示例
Jun 28 Python
Python 登录网站详解及实例
Apr 11 Python
Python中函数eval和ast.literal_eval的区别详解
Aug 10 Python
使用Python操作excel文件的实例代码
Oct 15 Python
django模板语法学习之include示例详解
Dec 17 Python
在python中,使用scatter绘制散点图的实例
Jul 03 Python
Django实现WebSSH操作物理机或虚拟机的方法
Nov 06 Python
mac使用python识别图形验证码功能
Jan 10 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中$_REQUEST、$_POST、$_GET的区别和联系小结
2011/11/23 PHP
Laravel框架中扩展函数、扩展自定义类的方法
2014/09/04 PHP
PHP构造二叉树算法示例
2017/06/21 PHP
AppBaseJs 类库 网上常用的javascript函数及其他js类库写的
2010/03/04 Javascript
在VS2008中使用jQuery智能感应的方法
2010/12/30 Javascript
gridpanel动态加载数据的实例代码
2013/07/18 Javascript
JavaScript实现仿新浪微博大厅和腾讯微博首页滚动特效源码
2015/09/15 Javascript
jQuery入门之层次选择器实例简析
2015/12/11 Javascript
【经验总结】编写JavaScript代码时应遵循的14条规律
2016/06/20 Javascript
jQuery实现的小图列表,大图展示效果幻灯片示例
2016/10/25 Javascript
5分钟快速掌握JS中var、let和const的异同
2018/09/19 Javascript
jquery+css实现Tab栏切换的代码实例
2019/05/14 jQuery
JS判断数组四种实现方法详解
2020/06/29 Javascript
[57:16]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第二场
2014/05/26 DOTA
python kmeans聚类简单介绍和实现代码
2018/02/23 Python
numpy中实现二维数组按照某列、某行排序的方法
2018/04/04 Python
python中的变量如何开辟内存
2018/06/26 Python
使用python实现快速搭建简易的FTP服务器
2018/09/12 Python
Python3爬虫爬取英雄联盟高清桌面壁纸功能示例【基于Scrapy框架】
2018/12/05 Python
python 删除字符串中连续多个空格并保留一个的方法
2018/12/22 Python
python实现抖音点赞功能
2019/04/07 Python
Python 等分切分数据及规则命名的实例代码
2019/08/16 Python
Python实现图像去噪方式(中值去噪和均值去噪)
2019/12/18 Python
Python3如何在Windows和Linux上打包
2020/02/25 Python
python模拟斗地主发牌
2020/04/22 Python
Python faker生成器生成虚拟数据代码实例
2020/07/20 Python
利用 Canvas实现绘画一个未闭合的带进度条的圆环
2019/07/26 HTML / CSS
大四学生毕业自荐信
2013/11/07 职场文书
架构师岗位职责
2013/11/18 职场文书
工程招投标邀请书
2014/01/30 职场文书
优秀士兵先进事迹
2014/02/06 职场文书
2015入党个人自传范文
2015/06/26 职场文书
2016年校长新年寄语
2015/08/17 职场文书
Nginx设置日志打印post请求参数的方法
2021/03/31 Servers
Win10 heic文件怎么打开 ? Win10 heic文件打开教程
2022/04/06 数码科技
CSS实现背景图片全屏铺满自适应的3种方式
2022/07/07 HTML / CSS