作者 | 灰小猿
责编 | 王晓曼
出品 | CSDN博客
最近在做项目开发的时候,跟小伙伴聊到修 Bug 这件事。
嗯,对于一只没技术的程序猿来说,修 Bug 的确是一件让人头疼的事情,尤其是对于比较大型的项目开发,在变量较多的时候,一次次的检查错误是真的让头发颤抖。
在这里想问一下有多少小伙伴是在 Python 中使用 print 来输出某个变量从而检查参数错误的?
嗯…没秃头以前我也是这样做的,后来我为了以后有更多的时间去修 Bug,慢慢的发现断言是个好东西,再后来为了直接观察到整个程序某个值的变化过程,发现还是日志处理是真香。
那么今天大灰狼就来和大家聊聊 Python 日志处理的那些梗!
记日志是一件很棒的事,它可以很好的帮助我们理解程序中发生的事以及事情发生的顺序。
在 Python 中记录程序运行的日志文件时,我们需要调用 logging 模块,通过该模块,我们很容易的创建自定义的消息记录,这些日志消息将描述程序执行时,何时达到日志函数的调用,并列出我们想要指定的任何变量当时的值。
另一方面来说呢,如果我们在日志文件中发现某些日志消息缺失,这就表明有一部分代码被跳过,从未执行。这意味着什么…嗯,我想作为程序猿的你应该也很清楚。
使用日志模块
使用日志消息要启用 logging 模块,在程序运行时将日志信息显示在屏幕上,所以我们当然需要先调用该模块了,并且输入以下代码:
#调用logging函数
import logging
logging.basicConfig(filename='logginginfo.txt', level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
这行代码的作用是定义的一个输出格式,输出某一条日志消息执行的时间。
当 Python 记录一个事件的日志时,它会创建一个 LogRecord 对象,保存关于该事件的信息,Logging 模块的函数让你能够指定看到这个 LogRecord 对象的细节,以及希望的细节展示方式。
值得注意的是,当我们想要将监控的值通过日志文件进行输出时,需要调用 logging.deBug 函数,并且该函数的输出方式与 print 相同,而这行消息输出值的格式,就是我们最开始在 logging.loasicConfig 中指定的,并且包括我们传递给 debug 的参数消息。
以一个计算阶乘的函数为例,我们监控该函数中每一个变量在程序运行时值的变化情况:
#阶乘计算日志消息输出实例
import logging
logging.basicConfig( level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
#logging.disable(logging.CRITICAL)
logging.debug("程序测试:")
def factorial(n):
logging.debug("阶乘数为:%s" %(n))
result = 1
for i in range(1, n + 1):
result *= i
logging.debug("此时乘的数为:%s, 结果是%s" %(i, result))
logging.debug('最终结果:%s' %(result))
return result
print(factorial(5))
运行结果:
通过这些日志消息的输出,我们就可以看到在程序执行时该循环内部发生的值的变动的情况,从打印出的日志文件可以看出,Logging.debug 函数不仅输出了我们所监控的变量的数值,并且输出了该函数在调用时的时间和单词 Bebug。
通过这样的一个日志我们就可以非常直观的看到程序在运行过程中的变化情况。
不要使用print调试程序
现在我们来聊一下,为什么不建议使用 print 函数进行值的监控输出,并不是说 pintf 函数不能够将我们监控的变量值输出。
而是我们在将程序调试完成的时候,需要花费很多时间从代码中清除每条日志消息中的 print 函数,这样的话,我们就很有可能一不小将我们期望输出的内容进行删除。
然而,日志消息就很好地避免了这一点,我们可以随心所欲的在程序中添加很多日志变量。
那可能就会有小伙伴问了,难道使用日志文件输出的内容在最后就不需要禁用了吗?
当然不是的,只是使用 logging.debug 输出的语句在最后不需要我们一个个的将其禁用,只需要调用 logging.disable(logging.CRITICAL) 就可以完全禁止日志输出。
不像print函数那样必须将每一行删除或注释掉,因此 logging.disable 模块让日志文件的显示和隐藏变得更加方便快捷。
哈哈,下一步你可能会认为我要说 logging.disable 函数的禁用功能了。
嗯…那接下来我们就来说一下Python中日志消息的级别,是不是很惊喜?没事,都会有的喔!
日志级别
我们所调用的日志文件是有日志级别的,“日志级别”提供了一种方式。
这种方式按重要性将日志消息进行了分类,五个日志级别如下表所示,从最不重要到最重要,利用不同的日志函数消息,可以按某个级别计入日志并且输出。
日志消息作为一个字符串,传递给这些函数,进行日志级别的划分只是为了方便对程序中可能出现的错误的异常判断,归根到底,具体使用哪种级别的日志消息,还是需要根据你的程序来定的。
日志级别的好处就在于,我们可以改变想要看到的日志消息的优先级,向 basicConfig 函数传入 logging DEBUG 作为 level 的关键字参数,这将显示所有日志级别的消息。
同时在进行某项程序开发的时候我们可能并不希望显示所有的日志消息,这样我们可以修改 level 的关键字参数。
例如:将 basicConfig 函数的 level 的关键字参数改为 logging.ERROR,这样将只显示 ERROR 级别和 CRITICAL 的日志消息,对于 ERROR 以下级别的日志消息并不会显示在屏幕上。
例如下面这行代码,我们只禁用 INFO 及以下级别的日志消息,则对于 INFO 以上的 WARNING 消息则不会禁用。
#日志禁用
import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
#禁用INFO及以下级别日志消息
logging.disable(logging.INFO)
logging.debug("程序测试:")
def factorial(n):
logging.debug("阶乘数为:%s" %(n))
result = 1
for i in range(1, n + 1):
result *= i
logging.debug("此时乘的数为:%s, 结果是%s" %(i, result))
logging.warning('最终结果:%s' %(result))
return result
print(factorial(5))
结果如下:
好了,聊完日志的级别,就该禁用日志出场了!
禁用日志
在调试完成以后,我们当然不希望所有这些日志出现在屏幕之上,这时我们需要调用 logging.disable 函数禁用这些消息,这样这些日志消息就不必进入到程序之中手动删除或者将所有日志注释掉,只需要向 logging.disable 传入一个级别,它就会禁止该级别和更低级的所有日志消息。
所以如果想要禁用所有日志,只需要向程序中添加:
logging.disable(logging.CRITICAL),
同时还有一点需要注意的是:logging.disable 函数将禁用它之后的所有该级别及以下的消息。
所以在这里我们就可以将禁用日志消息的 logging.disable 函数放在程序文件的最前方,调用 import logging 模块之下,这样就很容易找到,并且根据需要来注释掉,从而启用或禁用日志消息的作用。
将日志记录到文件
我们除了将日志消息显示在屏幕上以外,还可以将它们写入到文本文件之中,这样做目的是为了我们在进行程序调试的时候,不至于很多日志文件显示在屏幕,从而影响我们对变量的读取的读取,在 rogging.basicConfig 函数接收filename 关键字为参数,像这样:
#将日志写入文件
logging.basicConfig(filename='logginginfo.txt', level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
之后日志消息就会被保存到某一特定的文本文件中,同样使用求阶乘的函数,将日志消息存入 txt 文件中:
这样程序输出的结果中就只会有我们使用 print 想要输出的内容,对于日志消息,则会保存在相应的日志文件中去。
虽然日志消息很有用,但如果不存入文件显示,就可能会和我们想要输出的结果一同显示在屏幕上,让我们很难找到程序中真正的输出。将日志信息写入到文件以后,这样就会使屏幕变得干净整洁,就能够很好的保存信息。
这样在程序运行之后,如果发现某些程序错误,我们就可以直接在该文本文件中读取日志,查看变量信息。
版权声明:本文为CSDN博主「灰小猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:
https://blog.csdn.net/weixin_44985880/article/details/106179998