logging日志模块包括哪些部分,含义是什么
Admin 2022-06-24 群英技术资讯 275 次浏览
Python中自带的logging模块提供了标准的日志接口,在debug时使用往往会事半功倍。为什么不直接使用print去输出呢?这种方式对简单的脚本来说有用,对于复杂的系统来说相当于一个花瓶摆设,大量的print输出很容易被遗忘在代码里,并且print是标准输出,这很难从一堆信息里去判断哪些是你需要重点关注的。
logging的优势就在于可以控制日志的级别,把不需要的信息进行过滤,且可以决定它输出到什么地方、如何输出,还可以通过控制等级把特定等级的信息输出到特定的位置等。logging一共分为四个部分:
logging将logger的等级划分成5个level,由低到高分别是DEBUG、INFO、WARNING、ERROE、CRITICAL,默认是WARNING级别,CRITICAL最高,相关等级说明如下:
Level | 说明 |
---|---|
DEBUG | 输出详细的运行信息,主要用于调试,追踪问题时使用 |
INFO | 输出正常的运行的信息,一切按预期进行的情况 |
WARNING | 一些意想不到的或即将会发生的情况,比如警告:内存空间不足,但不影响程序运行 |
ERROR | 由于某些问题,程序的一些功能会受到影响,还可以继续运行 |
CRITICAL | 一个严重的错误,表明程序本身可能无法继续运行 |
这些等级的日志中低包含高,比如INFO,会收集INFO及以上等级的日志,DEBUG等级的日志将不进行收集。下面我们来输出这5个等级的日志:
import logging """ logging模块默认收集的日志是warning以上等级的 """ a = 100 logging.debug(a) logging.info('这是INFO等级的信息') logging.warning('这是WARNING等级的信息') logging.error('这是ERROR等级的信息') logging.critical('这是CRITICAL等级的信息')
输出结果:
C:\software\python\python.exe D:/learn/test.py
WARNING:root:这是WARNING等级的信息
ERROR:root:这是ERROR等级的信息
CRITICAL:root:这是CRITICAL等级的信息
Process finished with exit code 0
日志是怎么被收集和输出的呢?答案就是日志收集器,设置一个收集器,把指等级的日志信息输出到指定的地方,控制台或文件等,其工作过程大致如下:
logging中默认的日志收集器是root,收集等级默认是WARNING,我们可以通过setLevel来改变它的收集等级。
# 获取默认的日志收集器root my_log = logging.getLogger() # 设置默认的日志收集器等级 my_log.setLevel("DEBUG") # 日志将全部被收集 a = 100 logging.debug(a) logging.info('这是INFO等级的信息') logging.warning('这是WARNING等级的信息') logging.error('这是ERROR等级的信息') logging.critical('这是CRITICAL等级的信息')
输出结果:
C:\software\python\python.exe D:/learn/test.py
DEBUG:root:100
INFO:root:这是INFO等级的信息
WARNING:root:这是WARNING等级的信息
ERROR:root:这是ERROR等级的信息
CRITICAL:root:这是CRITICAL等级的信息
Process finished with exit code 0
除了使用默认的日志收集器,我们也可以自己创建一个收集器logging.getLogger,如下:
import logging my_logger = logging.getLogger('my_logger') # 创建logging对象 my_logger.setLevel('INFO') # 设置日志收集等级 a = 100 logging.debug(a) logging.info('这是INFO等级的信息') logging.warning('这是WARNING等级的信息') logging.error('这是ERROR等级的信息') logging.critical('这是CRITICAL等级的信息')
输出结果:
C:\software\python\python.exe D:/learn/test.py
WARNING:root:这是WARNING等级的信息
ERROR:root:这是ERROR等级的信息
CRITICAL:root:这是CRITICAL等级的信息
Process finished with exit code 0
上面例子中设置的收集器都是输出到控制台,除此我们还可以输出到文件中。
Handlers(处理器)的作用就是将logger发过来的信息进行准确地分配,送往正确的地方。比如,送往控制台、文件或者是两者。它决定了每个日志收集器的行为,是创建收集器之后需要配置的重点区域。每个Handler同样有一个日志级别,一个logger可以拥有多个handler也就是说logger可以根据不同的日志级别将日志传递给不同的handler。当然也可以相同的级别传递给多个handler,这就根据需求来灵活的配置了。
下面实例中设置了两个handler,一个是输出到控制台,一个是输出到文件中。关键代码:
logging.StreamHandler
:输出到控制台的处理器logging.FileHandler
:输出到文件的处理器addHandler
:添加处理器removeHandler
:移除处理器import logging my_logger = logging.getLogger('my_logger') my_logger.setLevel('INFO') # 创建一个输出到控制台的处理器 sh = logging.StreamHandler() sh.setLevel("ERROR") # 设置处理器的输出等级 my_logger.addHandler(sh) # 将处理器绑定到日志收集器上 # 创建一个输出到文件的处理器 fh = logging.FileHandler("logs.logs", encoding="utf8") fh.setLevel("INFO") my_logger.addHandler(fh) # my_logger.removeHandler(fh) # 移除处理器 a = 100 my_logger.debug(a) my_logger.info('这是INFO等级的信息') my_logger.warning('这是WARNING等级的信息') my_logger.error('这是ERROR等级的信息') my_logger.critical('这是CRITICAL等级的信息')
运行结果:
C:\software\python\python.exe D:/learn/test.py
这是ERROR等级的信息
这是CRITICAL等级的信息
Process finished with exit code 0
Filters可以实现比level更复杂的过滤功能,限制只有满足过滤规则的日志才会被输出。比如我们定义了filter = logging.Filter('A.B')
,并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带A.B前缀的Logger才能输出其日志。下面是一个简单实例:
import logging # 这是logger1 my_logger = logging.getLogger('A.C,B') my_logger.setLevel('INFO') # 这是logger2 my_logger2 = logging.getLogger('A.B') my_logger2.setLevel('INFO') # 创建一个处理器,两个logger都使用这个处理器 sh = logging.StreamHandler() sh.setLevel("ERROR") my_logger.addHandler(sh) my_logger2.addHandler(sh) # 创建一个过滤器绑到处理器上 my_filter = logging.Filter(name='A.B') sh.addFilter(my_filter) # 把过滤器添加到处理器上 # sh2.removeFilter(my_filter) # 移除过滤器 my_logger.debug('这是logger1-DEBUG等级的信息') my_logger.info('这是logger1-INFO等级的信息') my_logger.warning('这是logger1-WARNING等级的信息') my_logger.error('这是logger1-ERROR等级的信息') my_logger.critical('这是logger1-CRITICAL等级的信息') my_logger2.debug('这是logger2-DEBUG等级的信息') my_logger2.info('这是logger2-INFO等级的信息') my_logger2.warning('这是logger2-WARNING等级的信息') my_logger2.error('这是logger2-ERROR等级的信息') my_logger2.critical('这是logger2-CRITICAL等级的信息')
因为只有logger2满足过滤器的条件,因此只会输出logger2的日志,运行结果如下:
C:\software\python\python.exe D:/learn/test.py
这是logger2-ERROR等级的信息
这是logger2-CRITICAL等级的信息
Process finished with exit code 0
filter方法用于具体控制传递的record记录是否能通过过滤,如果该方法返回值为0表示不能通过过滤,非0表示可以通过过滤。
顾名思义,对日志进行格式化,因为常规的日志输出并不直观美观,通过美化日志的输出格式,可以让我们阅读起来更加舒服。
format常用格式如下:
%(name)s
: 打印收集器名称%(levelno)s
: 打印日志级别的数值%(levelname)s
: 打印日志级别名称%(pathname)s
: 打印当前执行程序的路径,其实就是sys.argv[0]%(filename)s
: 打印当前执行程序名%(funcName)s
: 打印日志的当前函数%(lineno)d
: 打印日志的当前行号%(asctime)s
: 打印日志的时间%(thread)d
: 打印线程ID%(threadName)s
: 打印线程名称%(process)d
: 打印进程ID%(message)s
: 打印日志信息import logging my_logger = logging.getLogger('A.C,B') my_logger.setLevel('INFO') # 创建一个处理器 sh = logging.StreamHandler() sh.setLevel("ERROR") my_logger.addHandler(sh) # 设置一个格式,并设置到处理器上 formatter = logging.Formatter('%(asctime)s - [%(filename)s-->line:%(lineno)d] - %(levelname)s: %(message)s') sh.setFormatter(formatter) my_logger.debug('这是logger1-DEBUG等级的信息') my_logger.info('这是logger1-INFO等级的信息') my_logger.warning('这是logger1-WARNING等级的信息') my_logger.error('这是logger1-ERROR等级的信息') my_logger.critical('这是logger1-CRITICAL等级的信息')
运行结果:
C:\software\python\python.exe D:/learn/test.py
2020-08-01 18:28:43,645 - [test.py-->line:17] - ERROR: 这是logger1-ERROR等级的信息
2020-08-01 18:28:43,645 - [test.py-->line:18] - CRITICAL: 这是logger1-CRITICAL等级的信息
Process finished with exit code 0
如果你用 FileHandler 存储日志,文件的大小会随着时间推移而不断增大,最终有一天它会占满你所有的磁盘空间。Python 的 logging 模块提供了两个支持日志滚动的 FileHandler
类,分别是 RotatingFileHandler 和 TimedRotatingFileHandler,它就可以解决这个尴尬的问题。
在实际应用中,我们通常会根据时间进行滚动,以下实例也以时间滚动为例,按大小滚动的同理:
import logging from logging.handlers import TimedRotatingFileHandler my_logger = logging.getLogger('A.C,B') my_logger.setLevel('INFO') # 创建一个处理器,使用时间滚动的文件处理器 log_file_handler = TimedRotatingFileHandler(filename='log.log', when='D', interval=1, backupCount=10) # log_file_handler.suffix = "%Y-%m-%d" # log_file_handler.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}.log$") log_file_handler.setLevel("ERROR") my_logger.addHandler(log_file_handler) # 设置一个格式,并设置到处理器上 formatter = logging.Formatter('%(asctime)s - [%(filename)s-->line:%(lineno)d] - %(levelname)s: %(message)s') log_file_handler.setFormatter(formatter) my_logger.debug('这是logger1-DEBUG等级的信息') my_logger.info('这是logger1-INFO等级的信息') my_logger.warning('这是logger1-WARNING等级的信息') my_logger.error('这是logger1-ERROR等级的信息') my_logger.critical('这是logger1-CRITICAL等级的信息')
参数说明:
filename
:日志文件名;
when
:是一个字符串,用于描述滚动周期的基本单位,字符串的值及意义如下:
interval
: 滚动周期,单位由when指定,比如:when='D',interval=1,表示每天产生一个日志文件;
backupCount
: 表示日志文件的保留个数;
除了上述参数之外,TimedRotatingFileHandler还有两个比较重要的成员变量,它们分别是suffix和extMatch。suffix是指日志文件名的后缀,suffix中通常带有格式化的时间字符串,filename和suffix由“.”连接构成文件名(例如:filename="test", suffix="%Y-%m-%d.log",生成的文件名为test.2020-08-01.log。extMatch是一个编译好的正则表达式,用于匹配日志文件名的后缀,它必须和suffix是匹配的,如果suffix和extMatch匹配不上的话,过期的日志是不会被删除的。比如,suffix=“%Y-%m-%d.log”, extMatch的只能是re.compile(r"^\d{4}-\d{2}-\d{2}.log$")。默认情况下,在TimedRotatingFileHandler对象初始化时,suffxi和extMatch会根据when的值进行初始化:
S:suffix="%Y-%m-%d_%H-%M-%S",extMatch=r"\^d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}"; M:suffix="%Y-%m-%d_%H-%M",extMatch=r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}"; H:suffix="%Y-%m-%d_%H",extMatch=r"^\d{4}-\d{2}-\d{2}_\d{2}"; D:suffxi="%Y-%m-%d",extMatch=r"^\d{4}-\d{2}-\d{2}"; MIDNIGHT:"%Y-%m-%d",extMatch=r"^\d{4}-\d{2}-\d{2}"; W:"%Y-%m-%d",extMatch=r"^\d{4}-\d{2}-\d{2}";
如果对日志文件名没有特殊要求的话,可以不用设置suffix和extMatch,如果需要,一定要让它们匹配上。
一次封装,一劳永逸,之后直接调用即可,封装内容按需。
import logging from logging.handlers import TimedRotatingFileHandler class MyLogger(object): @staticmethod def create_logger(): my_logger = logging.getLogger("my_logger") my_logger.setLevel("DEBUG") # 控制台处理器 stream_handler = logging.StreamHandler() stream_handler.setLevel("ERROR") my_logger.addHandler(stream_handler) # 使用时间滚动的文件处理器 log_file_handler = TimedRotatingFileHandler(filename='log.log', when='D', interval=1, backupCount=10) log_file_handler.setLevel("INFO") my_logger.addHandler(log_file_handler) formatter = logging.Formatter('%(asctime)s - [%(filename)s-->line:%(lineno)d] - %(levelname)s: %(message)s') stream_handler.setFormatter(formatter) log_file_handler.setFormatter(formatter) return my_logger
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
之前我们了解了用python实现扑克游戏中判断牌型的功能,那么游戏的下一步是对扑克牌比较大小,那么这个效果要如何实现呢?接下来我们继续尝试用Python来实现比较扑克牌大小。
本文为大家重点介绍如何通过 python 编码来实现我们的接口测试以及通过Pycharm的实际应用编写一个简单接口测试,感兴趣的可以了解一下
很多小伙伴在提到python数据可视化的时候第一反应就是matplotlib库,但实际上python还有很多很好用的数据可视化的库,下面这篇文章主要给大家介绍了关于如何利用Python抓取数据并可视化的相关资料,需要的朋友可以参考下
这篇文章主要为大家介绍了一些在Python中常用的图片处理函数的使用,例如split()、merge()、threshold()、applyColorMap()等,需要的可以参考一下
这篇文章主要介绍了Python-OpenCV的基本使用和相关函数介绍,主要包括图像的读取保存图像展示问题,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008