logging模块的使用
这个模块为应用与库实现了灵活的事件日志系统的函数与类。
使用标准库提供的 logging API 最主要的好处是,所有的 Python 模块都可能参与日志输出,包括你自己的日志消息和第三方模块的日志消息。
导入模块
import logging
不需要下载,是python的内置模块。
简单使用
简单使用可以代替print函数来进行代码的调试。据说日志输出要比print输出要快一些,而且还是线程安全的(即在使用多线程或线程池时输出的结果是有序的)。
logging.debug('调试中...')
logging.info('输出的信息...')
logging.warning('warning!')
logging.error('出现错误!')
logging.critical('严重错误!')
运行结果:
只输出了三条信息,这是因为日志是有一个级别的,而默认是warning级别,而比warning级别低的语句就不会输出。
可以自己设置日志级别,来输出全部的日志结果。
logging.basicConfig(level=logging.DEBUG)
需要使用 Logging 的原因各有不同。这些原因可以根据严重性的不同分为如下几类。
默认的级别时WARNING,意味默认的级别下,显示的日志信息必须时 >=
WARNING的级别才会进行输出。
日志的记录可以由不同的方式,最简单的是把日志直接输出到console,另外一种就是可以把他们写到文件。
将日志输出到文件中
# 输出到日志文件中
logging.basicConfig(level=logging.INFO,
filename='log.txt',
filemode='w') # 默认filemode 是追加写入的方式
logging.debug('调试中...')
logging.info('输出的信息...')
logging.warning('warning!')
logging.error('出现错误!')
logging.critical('严重错误!')
运行结果:
有没有发现输出到文件中是不是少了debug的信息😃,细心的朋友肯定能知道是因为设置的日志级别是info, debug级别比info低自然不会输出啦。
来继续学习,仅仅这样可不够😁
将日志输出到控制台
废话,不加filename不就好啦。🙄
日志输出格式美化
# 美化日志输出
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(lineno)s >>> %(message)s', # %()s 是固定格式
datefmt='%Y-%m-%d %H:%M:%S')
logging.info('这是一条正常信息')
logging.warning('这是一条警告信息')
logging.error('这是一条错误信息')
logging.critical('这是一条致命的错误信息')
运行结果:
更多的format参数:
高级应用
在官方文档中有4个重要的对象,分别是logger(记录器)、handler(处理器)、filter(过滤器)、formatter(格式器)。
-
记录器对象
提供应用程序代码能直接使用的接口
-
处理器对象
将记录器产生的日志发送到目的地(控制台或文件)
-
过滤器对象
提供更好的粒度控制,决定哪些日志会被输出
-
格式化器对象
设置日志内容的组成结构和消息字段
# logger记录器
'''
1. 提供应用程序的调用接口
logger = logging.getLogger(__name__) 默认是root, 也可以自定义其他
2. 决定日志记录的级别
logger.setLevel()
3. 将日志内容传递到相关联的handler中
logger.addHandler() 和 logger.removeHandler()
'''
# handler处理器
'''
# 最常用的两个 StreamHandler 和 FileHandler
# 所有的Handler处理器都可以使用 setFormatter() 来设置当前Handler对象的消息格式
'''
# formatter格式器
'''
ft = logging.Formatter(fmt=None, datefmt=None, style='%')
style参数默认为%, 这表示 %(<dictionary key>)s 格式的字符串
'''
需求:我们即想在控制台输出日志,也想在文件中输出日志时,高级的做法
# 记录器
logger = logging.getLogger('redballoon')
logger.setLevel(level=logging.INFO)
# print(logger)
# 处理器
# 定义StreamHandler输出到控制台
console_handler = logging.StreamHandler()
#定义FileHandler输出到日志文件
file_handler = logging.FileHandler(filename='2023-3-18-log.txt')
console_handler.setLevel(level=logging.DEBUG)
# 如果没有给handler设置日志级别,将使用logger的日志级别
# file_handler.setLevel(level=logging.INFO)
# * 若是设置了logger记录器的日志级别,又设置了console_handler的日志级别,则会以logger的级别为准。
# 格式化器
fmt = logging.Formatter('%(asctime)s %(levelname)s %(filename)s:%(lineno)s >>> %(message)s')
# 给处理器添加格式
console_handler.setFormatter(fmt)
file_handler.setFormatter(fmt)
# 给记录器添加处理器
logger.addHandler(console_handler)
logger.addHandler(file_handler)
logger.debug('这是调试的信息')
logger.info('这是一条正常信息')
logger.warning('这是一条警告信息')
logger.error('这是一条错误信息')
logger.critical('这是一条致命的错误信息')
控制台运行结果:
日志文件结果:
哎,有问题呀,我想要的是控制台输出dubug的级别,日志文件输出info的级别。现在这咋都一样啊。
1.这是因为我前面说过,如果同时设置了console_handler的级别和logger的日志级别,则会以logger的级别为准。
2.而如果不设置logger的日志级别,则会是默认的warning级别。
想要解决,就设置logger的日志级别为最低的debug级别,再分别设置console_handler 和 file_handler的日志级别就好啦。
修改后代码如下:
# 记录器
logger = logging.getLogger('redballoon')
logger.setLevel(level=logging.DEBUG)
# 处理器
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler(filename='2023-3-18-log.txt')
console_handler.setLevel(level=logging.DEBUG)
# 如果没有给handler设置日志级别,将使用logger的日志级别
file_handler.setLevel(level=logging.INFO)
# * 若是设置了logger记录器的日志级别,又设置了console_handler的日志级别,则会以logger的级别为准。
# 格式化器
fmt = logging.Formatter('%(asctime)s %(levelname)s %(filename)s:%(lineno)s >>> %(message)s')
# 给处理器添加格式
console_handler.setFormatter(fmt)
file_handler.setFormatter(fmt)
# 给记录器添加处理器
logger.addHandler(console_handler)
logger.addHandler(file_handler)
logger.debug('这是调试的信息')
logger.info('这是一条正常信息')
logger.warning('这是一条警告信息')
logger.error('这是一条错误信息')
logger.critical('这是一条致命的错误信息')
Filters
可被 Handlers
和 Loggers
用来实现比按层级提供更复杂的过滤操作。
使用场景,在有多个记录器时,如果想指定输出某一个的信息可使用过滤器。
通过记录器名称来设置过滤器,满足我们设置的名称便会被输出
# 记录器
logger1 = logging.getLogger('redballoon')
logger2 = logging.getLogger('blueballoon')
logger1.setLevel(level=logging.DEBUG)
# logger2.setLevel(level=logging.DEBUG) 不设置让他为默认级别
# 处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(level=logging.DEBUG)
# 过滤器 满足过滤器设置的记录器名称便会被输出
# 定义一个过滤器
flt = logging.Filter('blueballoon')
# 关联过滤器
console_handler.addFilter(flt)
# 格式化器
fmt = logging.Formatter('%(name)-12s | %(asctime)s %(levelname)s %(filename)s:%(lineno)s >>> %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',)
# 给处理器添加格式
console_handler.setFormatter(fmt)
# 给记录器添加处理器
logger1.addHandler(console_handler)
logger2.addHandler(console_handler)
logger1.debug('这是调试的信息')
logger1.info('这是一条正常信息')
logger1.warning('这是一条警告信息')
logger1.error('这是一条错误信息')
logger1.critical('这是一条致命的错误信息')
print('=========================================')
logger2.debug('这是调试的信息')
logger2.info('这是一条正常信息')
logger2.warning('这是一条警告信息')
logger2.error('这是一条错误信息')
logger2.critical('这是一条致命的错误信息')
运行结果:
可以看到只输出了记录器为 blueballoon 的日志信息。
以上就是本菜鸟的学习笔记和理解,希望对你们有用。