40035小游戏,menest,景德镇房产
1 引言
最近在开发一个自动化测试系统,为方便调试和后期维护,在代码中添加了日志,用的是python内置的logging模块,看了许多博主的博文,颇有所得。不得不说,有许多博主大牛总结得确实很好。似乎我再写关于logging的博文有些多余,但不写总结又总觉得没掌握。那就写写吧,也方便日后回顾。
开始总结之前,先感谢几位博主,他们的博客写得很是详尽:
云游道士的博文:
说说为什么需要添加日志?
就像上面说的,为了调试和后期维护方便。也许在开发中没有太大体会,但是如果将软件部署到了生产环境中,一旦出现bug,没有日志,就很难对当时的情况进行追踪,有了日志,就可以根据日志尽可能的对当时的数据环境进行还原,方便debug。甚至,只要日志设计得足够合理,还可以用于后续业务数据分析等。
2 日志等级
为什么需要对日志进行划分等级呢?
当我们出于开发时debug的目的使用日志时,我们自然是想尽可能详尽得记录日志,但是如果部署到生产环境中,这样做就可能因为大量的io占用服务器资源,所以在生产环境中就只需要记录异常信息、错误情况等就好了。
所以,给日志设置等级,可以方便得、因地制宜控制日志输出。
这里只介绍python的logging模块的日志等级(当然,其他日志系统的日志等级划分事实上也基本相同)。logging的日志等级包括5个:
日志等级(level)
|
描述
|
debug
|
最详细的日志信息,典型应用场景是 问题诊断
|
info
|
信息详细程度仅次于debug,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
|
warning
|
当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
|
error
|
由于一个更严重的问题导致某些功能不能正常运行时记录的信息
|
critical
|
当发生严重错误,导致应用程序不能继续运行时记录的信息
|
日志等级从上到下依次提高,当在程序中设定某个日志等级之后,比设定的日志等级低的日志记录将会被忽略,即logging就只会输出大于和等于设定的等级的日志。我们将在下文中通过代码示例证明这一点。
3 记录日志
logging模块提供两种方法记录日志:
(1)通过logging模块提供的模块级函数记录日志;
(2)通过logging模块提供的4大组件记录日志。
3.1 记录日志之logging模块级函数
在logging模块中,分别给出一个模块级别函数与上面说到的日志级别相对应,用于输出对应级别日志记录:
函数
|
说明
|
logging.debug(msg, *args, **kwargs)
|
创建一条严重级别为debug的日志记录
|
logging.info(msg, *args, **kwargs)
|
创建一条严重级别为info的日志记录
|
logging.warning(msg, *args, **kwargs)
|
创建一条严重级别为warning的日志记录
|
logging.error(msg, *args, **kwargs)
|
创建一条严重级别为error的日志记录
|
logging.critical(msg, *args, **kwargs)
|
创建一条严重级别为critical的日志记录
|
也有一个函数汇总了上面5个函数的功能:
函数
|
说明
|
logging.log(level, *args, **kwargs)
|
创建一条严重级别为level的日志记录
|
现在可以来尝试使用一下上面的函数了:
import logging
logging.debug('debug')
logging.info('info')
logging.warn('warn')
logging.error('error')
logging.critical('critical')
logging.warn('today is %s',datetime.date.today())
运行结果如下:
warning:root:warn
error:root:error
critical:root:critical
warning:root:today is 2019-03-28
上面的函数都有*args, **kwargs这两个参数,所以这些函数可以接受任意位置参数和关键字参数,这些参数填充到第一个参数msg,最后一条日志输出中添加了当前日期就是利用了这个功能。
那为什么会只输出后面3条日志记录呢?上面说到过,logging就只会输出大于和等于设定的等级的日志记录,而logging的默认日志等级是warning,所以日志等级为debug和info的两条记录都没有被输出。
如果想要输入日志等级为debug和info的日志记录,就要对logging进行配置。logging也提供了一个模块级别的专用于配置logging的函数:
函数
|
说明
|
logging.basicconfig(**kwargs)
|
对root logger进行一次性配置
|
尝试使用一下这个配置函数:
import logging
logging.basicconfig(level=logging.debug) # 设置日志等级
logging.debug('debug')
logging.info('info')
logging.warn('warn')
logging.error('error')
logging.critical('critical')
运行结果如下:
debug:root:debug
info:root:info
warning:root:warn
error:root:error
critical:root:critical
看,日志等级为debug和info的两条记录也都得到了输出。
上面表格对logging.basicconfig函数的说明中指出,logging.basicconfig函数时一次性配置,什么意思呢?意思就是说,logging.basicconfig函数只在第一次运行(第一次对logging进行配置)时起作用,后面在此设置其他参数是不会生效的。通过代码证明一下:
import logging
logging.basicconfig(level=logging.debug) # 设置日志等级
logging.basicconfig(level=logging.info) # 重新设置日志等级
logging.debug('debug')
logging.info('info')
logging.warn('warn')
logging.error('error')
logging.critical('critical')
运行结果:
debug:root:debug
info:root:info
warning:root:warn
error:root:error
critical:root:critical
看到没,debug级别日志记录还是输出了,证明重新运行logging.basicconfig函数设置日志级别没有生效。
另外需要注意的是,一定要在使用logging记录日志之前使用logging.basicconfig进行配置,否则,不会有任何输出。
我们再观察一下上面的程序输出,可以发现,每一条输出的结果里,不仅仅只有我们输出的字符串参数,还有其它的一些信息,例如日志等级,日志器名称(默认是root),分隔符(这里是冒号)等,这些都是logging默认给我配置好的,当然,我们也可以通过logging.basicconfig函数的各参数自定义logging的输出。
参数名称
|
描述
|
filename
|
指定日志输出目标文件的文件名,指定该设置项后日志信心就不会被输出到控制台了
|
filemode
|
指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效
|
format
|
指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。
|
datefmt
|
指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效
|
level
|
指定日志器的日志级别
|
stream
|
指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 valueerror异常
|
style
|
python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%'
|
handlers
|
python 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发valueerror异常。
|
上表中的参数format可以通过logging模块中定义好模式来设定值:
字段/属性名称
|
使用格式
|
描述
|
asctime
|
%(asctime)s
|
将日志的时间构造成可读的形式,默认情况下是‘2019-03-28 00:00:00,000’的形式,精确到毫秒
|
name
|
%(name)s
|
所使用的日志器名称,默认是'root',因为默认使用的是 rootlogger
|
filename
|
%(filename)s
|
调用日志输出函数的模块的文件名; pathname的文件名部分,包含文件后缀
|
funcname
|
%(funcname)s
|
由哪个function发出的log, 调用日志输出函数的函数名
|
levelname
|
%(levelname)s
|
日志的最终等级(被filter修改后的)
|
message
|
%(message)s
|
日志信息, 日志记录的文本内容
|
lineno
|
%(lineno)d
|
当前日志的行号, 调用日志输出函数的语句所在的代码行
|
levelno
|
%(levelno)s
|
该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)
|
pathname
|
%(pathname)s
|
完整路径 ,调用日志输出函数的模块的完整路径名,可能没有
|
process
|
%(process)s
|
当前进程, 进程id。可能没有
|
processname
|
%(processname)s
|
进程名称,python 3.1新增
|
thread
|
%(thread)s
|
当前线程, 线程id。可能没有
|
threadname
|
%(thread)s
|
线程名称
|
module
|
%(module)s
|
调用日志输出函数的模块名, filename的名称部分,不包含后缀即不包含文件后缀的文件名
|
created
|
%(created)f
|
当前时间,用unix标准的表示时间的浮点数表示; 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值
|
relativecreated
|
%(relativecreated)d
|
输出日志信息时的,自logger创建以 来的毫秒数; 日志事件发生的时间相对于logging模块加载时间的相对毫秒数
|
msecs
|
%(msecs)d
|
日志事件发生事件的毫秒部分。logging.basicconfig()中用了参数datefmt,将会去掉asctime中产生的毫秒部分,可以用这个加上
|
所以,结合上表中的内容,我们可以实现让每一条日志记录输出事件发生时间、事件发生位置、日志级别、事件内容等信息。
现在,我们来给刚才的日志添加一些输出,例如每条日志输出日志时间、日志级别、所在模块名、函数名、行号等信息,并指定时间输出格式,最后把日志输出到当前目录下的.log文件中。代码如下:
import logging
fmt = '%(asctime)s , %(levelname)s , %(filename)s %(funcname)s line %(lineno)s , %(message)s'
datefmt = '%y-%m-%d %h:%m:%s %a'
logging.basicconfig(level=logging.debug,
format=fmt,
datefmt=datefmt,
filename=".log")
logging.debug('debug')
logging.info('info')
logging.warn('warn')
logging.error('error')
logging.critical('critical')
运行上述代码后,控制台不会再有输出了,但当前目录下的.log文件会写入一下内容:
2019-03-28 16:34:08 thu , debug , log_test.py <module> line 8 , debug
2019-03-28 16:34:08 thu , info , log_test.py <module> line 9 , info
2019-03-28 16:34:08 thu , warning , log_test.py <module> line 10 , warn
2019-03-28 16:34:08 thu , error , log_test.py <module> line 11 , error
2019-03-28 16:34:08 thu , critical , log_test.py <module> line 12 , critical
3.2 记录日志之logging四大组件
logging四大组件是logging日志记录的高级用法。四大组件包括logger、handelr、filter、formater,且都是以类的形式来使用。logging四大组件协同工作流如下如所示:
各组件功能如下:
组件名称
|
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!!
点击进行留言回复
相关文章:
-
-
python如何查看网页代码
用python查看网页代码的方法:1、使用“import”导入requests包import requests2、使用requests包的get()函数通过网页...
[阅读全文]
-
-
python如何保存文本文件
python保存文本文件的方法:使用python内置的open()类可以打开文本文件,向文件里面写入数据可以用write()函数,写完之后,使用close()函...
[阅读全文]
-
python如何编写win程序
python可以编写win程序。win程序的格式是exe,下面我们就来看一下使用python编写exe程序的方法。编写好python程序后py2exe模块即可将...
[阅读全文]
-
-
-
-
-
-
|
网友评论