- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章神器 Logging,你真的了解吗?由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
logging 是 python 标准模块,用于记录和处理程序中的日志.
功能很强大,官方文档很详细,网上也有大量的说明和教程,但是对很多初次接触的同学来说,存在一些障碍.
一是因为标准库文档太过繁琐,需要较高的理论基础,着急用时,常常被文档搞晕.
二是大部分说明材料要么是官方文档的罗列,要么是简单的应用,对实际应用帮助不大.
今天,我们从应用上的一些问题开始,探讨一下日志神器 logging 极其背后的原理,让它能真正的帮助到我们.
debug 是日志模块中的一个日志等级为 DEBUG 的日志生成方法,还有 info、warning、error、critial,这里用 debug 做为代表进行说明.
我们常会看到,一会儿用 logging.debug 记录日志,一会儿又用 logger.debug 记录日志,到底该用什么?
先看代码
首先 logging 是作为一个模块被引入的。logging.debug 用的是 logging 模块的模块方法.
logger 是用 logging.getLogger() 生成的,是一个 日志对象,logger.debug 调用的是 logger 这个日志对象的方法.
上面的代码中 logging.debug 和 logger.debug 的效果完全是一样的.
这是因为,为了让开发者方便使用,logging 模块提供了一些列模块方法,如 debug,在引入模块后,就可以直接使用。这样开发者就不必关心日志模块的细节,像用 print 一样输出日志.
如果需要对日志输出进行定制化,比如将日志输出到文件中,过滤某些级别的日志,就需要创建或者得到一个实际的日志对象来处理,如上面代码中通过 getLogger 方法得到的日志对象.
我们知道,程序设计里要避免重复的设计,如果模块方法采用一套机制,日志对象上的方法采用另一套机制,就会出现重复造轮子的问题.
所以在使用模块方法,logging 其实创建了一个日志对象 —— root logger.
也就是 logging.debug 这个调用,实质上是调用 root logger 的日志方法.
相当于默认情况下 root logger 会作为日志处理对象.
如何获得 root logger 对象呢?
通过不带参数的 logging.getLogger() 方法获得.
那么 logging.debug 和 rootLogger.debug 是一会事,可以理解(但不严谨)为 logging.debug 是 rootlogger.debug 的快捷方式.
稍加留意就会观察到,程序是有层次结构的,通过相互引用,调用形成一个树状结构.
程序加载的地方是树根,比如 python 中要运行的代码文件,我们称之为 main。从树根开始长出其他枝叶。对于一个模块来说,又会形成一个自己的树.
如何用日志清楚地记录层次结构呢?
虽然直接打印出调用堆栈也可以看到调用结构,不过不太直观,缺乏业务逻辑描述.
而用 print 来打印出层次结构,需要编写大量的代码才能反射出(通过运行状态获取代码状态的一种方式)调用环境.
logging 提供了完毕的解决方案.
前面提到的 root logger 就是整个日志树的根,其他所有的 logger 都是从 root logger 伸展出来的枝叶。只要通过 getLogger(loggername) 方法获得的 logger 对象,都是伸展自 root logger 的.
如何向下伸展呢?
很简单,就像引用模块的层次关系一样,用 . 分隔层次就好了,例如:
语句 logging.getLogger('mod1.mod2.mod3') 实际上创建了三个 logger,名称分别是 mod1、mod1.mod2 和 mod1.mod2.mod3 。
mod1 为根,mod1.mod2 为子,mod1.mod2.mod3 为孙.
如果在 mod1 上设置了日志处理器(handler),那么其他两个的日志对象都会用到这个处理器.
这样不但记录的日志更清晰而且,可以为同一个根的日志对象设置可以共享的日志处理方式.
这样感觉也不方便,需要些那么多层次,如何才能更方便呢?在下面的 实践参考 里会有说明.
说完了日志模块的树状结构,来看看一个很常用的设置方法 basicConfig.
它可以方便的设置日志处理和记录方式,如没必要,不用为每个日志对象单独设置.
根据第一节的分析,我们知道,直接使用模块方法,用的其实是 root logger,那么就能明白 basicConfig 设置了 root logger 的日志处理方式.
这就意味着
一旦设置了通过 logging.basicConfig 设置了日志处理方式,其他所有日志都很受到影响.
另外 basicConfig 是个一次性方法,即
只有第一次设置有效,其后设置无效 。
本来是个一劳永逸的方法.
但用错了地方,就会很麻烦.
看下例子:
这段代码中,用 logging.basicConfig 对日志做了设置,意思是后面的日志都按照这样的方式输出.
但它是一个底层模块 —— pymysqlpool[1].
pymysqlpool 封装了 pymysql[2] 模块,提供了链接池特性,在多线程处理数据库场景下很有用.
也就是说,pymysqlpool 只会被引用加载,不会作为 main 被加载,这就比较尴尬了,因为 main 中对日志的设置就没有效果.
作为一个服务类模块(相对于业务的底层模块),不要通过 basicConfig 来设置日志模式,要么通过自己专属的日志对象来设置,要么不去设置,统一交给 main 去设置,例如:
如果为了测试,可以在测试的初始化方法中,使用 basicConfig 来设置,因为测试时,模块往往是被作为程序入库加载的.
了解了日志模块的一下特性,和其中的原理之后,这里有几条实践参考.
例如 from a.b.c import b 模块 c 中的 __name__ 值就为 a.b.c.
通过命令行参数设置不同类型的日志,见代码:
代码有点长,但不难懂.
python 为我们提供了很多便利的功能,有些需要真的用到才能有所体会,所以在遇到问题时,需要多研究一下,找到其中的特点和内在的原理或机制,这样就能更好的应用了.
在我理解了 logging 的原理之后,已经在我的很多项目中发挥了巨大作用,而且再也不必纠结于怎么用,如何更合理等这些问题了.
期望这篇文章也能对你有所帮助,比心.
参考资料 。
[1]pymysqlpool: https://pypi.org/project/pymysql-pool/ 。
[2]pymysql: https://pypi.org/project/PyMySQL/ 。
原文链接:https://mp.weixin.qq.com/s/k9ebCsG27tikSbX9eJqD0w 。
最后此篇关于神器 Logging,你真的了解吗?的文章就讲到这里了,如果你想了解更多关于神器 Logging,你真的了解吗?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个库项目,在 Android Studio 1.3.0 上开发并部署到 Artifactory Open Source Local Repository (3.5) 但是当我尝试在应用程序项目中
logging 是 python 标准模块,用于记录和处理程序中的日志。 功能很强大,官方文档很详细,网上也有大量的说明和教程,但是对很多初次接触的同学来说,存在一些障碍。 一是因为标准库文
我正在尝试使用 Maven 生成用于在 Vignette Portal 上部署的工件。包装与war完全一样工件但文件应该有 car取而代之。 我尝试过但无法完成的选项。 使用 war 插件并重命名最终
为什么 Points AdditiveBlending 只在从右看而不是从左看时有效?设置 depthTest:false 会解决问题,但会引发另一个问题,即点覆盖其他网格。 My fir
我对 UITextField 在动画 block 中移动时出现的工件有疑问... 在我移动我的 UITextField 之前它看起来像这样: 像这样移动之后: 我的猜测是它与 UITextField
单击此导航菜单中的第一个下拉菜单后,它将按预期加下划线,一旦菜单失去焦点(即单击页面上的其他位置),标签末尾的下划线不会被删除。 仅在 Chrome(版本 45.0.2454.85 m)中发生 我希望
我有一个简单的“hello world”C++ 项目:https://github.com/RomainGoussault/Deepov 我使用 Eclipse IDE for C/C++ Devel
使用方法有两种,可以用 XShell 或 Putty 上去命令查看,也可以生成 html 报告。 下面介绍GoAccess 在 CentOS 上的安装方法: 1. 需要安装 GeoIP, ncu
我一整天都在尝试将我的 javafx 应用程序转换为 jar 文件。我正在使用 Java 1.7 更新 7。 Oracle 有 some information ,但它似乎散落在各处。 Intelli
我实际上希望通过项目中的传递依赖项获得 powermock 1.5.6 版,但我只得到 1.4.11。这是什么意思? 最佳答案 在解析依赖项时,Maven 将更喜欢 POM 部分中指定的版本,而不是从
是否有公开可用的 maven 存储库将 Apache Tomcat 二进制分发 ZIP 托管为 maven Artifact (我的意思是可以通过 http://tomcat.apache.org 下
我希望在单击时播放 mp4 工件文件。 但是,当我点击mp4工件文件时,它看起来像下图。它不播放 如果我下载它然后我可以在我的本地 PC 上播放它。 所以我尝试了 HTML5 嵌入功能来流式传输它。我
我在 VSTS 上设置了构建/测试/发布。我们还有另一个管道(在 Linux 中)从具有给定构建 ID 的构建系统中获取构建工件。那么有没有办法从 Linux 上的 VSTS 下载构建工件?我发现不登
用 Ventoy 创建多启动 U 盘,你将永远不会缺少自己喜欢的 Linux 发行版。 给朋友和邻居一个可启动 U 盘,里面包含你最喜欢的 Linux 发行版,是向 Linux 新手介绍我们都
API 管理工具可以说是每个前端/后端开发必备的工具了,一个好的 API 管理工具可以提高团队的工作效率。 目前市面上有不少 API 相关的工具,比如 Postman、swagger 等。最近我也尝试
我有一个关于 JFrog Artifactory 用于在 Artifact 中查找“事物”的 AQL( Artifact 查询语言)的问题。 AQL 似乎非常强大,但我想知道如何使用正确的术语构建(正
我正在使用 Maven 3.1.1、Java 6 和 JBoss 7.1.3。我想在我的 JSP 上将对象呈现为 JSON,但是当我将其包含在我的 pom 中时
每次我对 POM 进行最微小的更改时,Intellij 都会删除项目结构输出目录设置中分解 Artifact 的 .war 扩展名。这会导致 Intellij 的运行/调试配置出错: Artifact
我的目标是进行对象跟踪。 我有一个 UWP c# 应用程序和链接的 c++ windows 运行时组件。在那里我可以获得对 opencv 的访问权限。 在 c# 中,MediaCapture 返回 S
遵循 http://doc.gitlab.com/ee/ci/yaml/README.html 的文档设置文件 .yml 我通过创建 artifacts 发现了问题,当构建要下载此 ZIPAPK 文件
我是一名优秀的程序员,十分优秀!