日志的作用是记录信息,便于查看问题,定位问题
logging 是Python中的一个标准库,在编码过程中,需要记录程序的运行,这时候,就需要用到 logging 模块。
日志级别
日志类型 | 权重 | 说明 |
---|
noset | 0 | 等于没写,相当于注释 | debug | 10 | 调试,记录一些额外信息,往往与主体内容无关,起到备注的作用 | info | 20 | 记录主体信息,例如程序的运行、数据及代码逻辑的走向 | warning | 30 | 警告,程序下次运行可能要出错,或已有内容进行修改,将不再适用 | error | 40 | 产生了报错,影响部分功能 | critical | 50 | 产生了严重报错,影响系统功能 |
test1.py
import logging
logging.debug("这里是调试信息")
logging.info("这是一条记录程序运行的信息")
logging.warning("警告:该方法在2.2版本后将不再适用")
logging.error("程序运行产生报错")
logging.critical("系统运行错误")
运行该py文件
WARNING:root:警告:该方法在2.2版本后将不再适用
ERROR:root:程序运行产生报错
CRITICAL:root:系统运行错误
可以发现,debug 和info 级别的日志,并没有在控制台打印出来 这里的root 是收集器的名字,后面会具体介绍
日志的级别,是自己定义的,为的就是在程序运行过程中,记录相应的信息,方便我们查看系统的运行情况
test2.py
import logging
def testfunc():
logging.info("调用了testfunc方法")
logging.warning("该方法在2.3版本将废弃,请使用新方法")
try:
1 / 0
except Exception as e:
logging.error(e)
if __name__ == '__main__':
testfunc()
运行结果
WARNING:root:该方法在2.3版本将废弃,请使用新方法
ERROR:root:division by zero
info 级别的日志,不会在控制台打印出来,打印了warning 和error 级别的日志。 1 / 0 产生了报错,e 是相应的报错信息,所以 logging.error(e) 将报错信息 division by zero 除数为0,打印了出来
收集与处理日志
在此之前,需要先了解以下几个概念:
- 日志收集器 logger
- 日志收集器level级别
- 日志处理器 handler
- 日志处理器级别设置
- 设置日志格式 fomat
- 添加日志处理器
import logging
logger = logging.getLogger('tester_logger')
logger.setLevel('DEBUG')
console_output_handler = logging.StreamHandler()
file_output_handler = logging.FileHandler("log.txt",encoding='utf-8')
console_output_handler.setLevel('DEBUG')
file_output_handler.setLevel('INFO')
logger.addHandler(file_output_handler)
logger.addHandler(console_output_handler)
fmt = logging.Formatter("%(asctime)s-%(filename)s-%(lineno)d-%(message)s")
console_output_handler.setFormatter(fmt)
file_output_handler.setFormatter(fmt)
logger.debug("hello")
logger.info("world")
logger.warning("!")
通过 logging.getLogger() 初始化logger收集器,这里 tester_logger 是收集器的名字,然后将 tester_logger 用变量 logger 接收。 日志收集器相当于一本笔记本,就比如上学的时候,不同的科目,需要用不同的笔记本,tester_logger 就是不同笔记本的名字。
通过logger.setLevel() 设置日志收集器level级别。 就比如一些简单的笔记 1+1=2 ,这种就不需要记录了,需要记录的是公式、解题思路。 一般情况下,日志收集器level级别会设置为 info 或 debug ,logger.setLevel('INFO') ,这样设置后,低于 debug 级别 的日志内容,将不会进行收集(debug 级别在收集范围内)
日志处理器 handler,handler的作用是定义处理日志的规则。 就相当于记笔记的笔,例如错题会用红色的笔记录,公式会用蓝色的笔记录,知识点会用黑色的笔记录。
-
输出方式 handler默认输出到控制台 logging.StreamHandler() 表示输出到控制台,logging.FileHandler() 表示输出到file文件中。一般情况下,都需要通过输出到文件中记录日志 定义了输出方式之后,通过 logger.addHandler() 将规则添加到 handler中 -
输出级别 handler默认为warning级别 通过 file_output_handler.setLevel('INFO') 设置handler的级别为 info ,低于 info 级别 的日志内容,将不会进行处理(info 级别在处理范围内)
可以发现,log.txt 文件夹中,只记录了 world 和 ! 。虽然日志收集器level级别为 debug ,但是日志处理器handler级别为 info ,所以,文件中只输出了info 级别 的日志内容。这两者是一个交集的关系,只选择级别最高的。 而控制台打印的,是 hello 、world 和 ! 。因为日志收集器level级别为 debug ,但是日志处理器handler级别也为debug 。
通过 logging.Formatter() 输出指定的日志格式,需要严格按照%()s 、%()d 或%()f 的规则定义格式的内容,内容与内容之间,可用 : 或 - 隔开
常用内容:
- asctime:代码执行时的时间
- funcName:执行函数的名字
- filename:模块(py文件)名字
- lineno:运行代码的行号
- levelname:日志处理器 handler名称
- message:提示的信息
2021-07-27 00:20:32,117-test3.py-32-hello
2021-07-27 00:20:32,118-test3.py-33-world
2021-07-27 00:20:32,119-test3.py-34-!
封装
logging日志功能,可以将其封装成一个独立的模块,这样,在需要使用到日志功能的地方,导入这个模块即可以使用
my_logger.py
import logging
class LoggerHandler():
def __init__(self,
name='root',
logger_level= 'DEBUG',
file=None,
logger_format = '%(asctime)s-%(filename)s-%(lineno)d-%(message)s'
):
logger = logging.getLogger(name)
logger.setLevel(logger_level)
fmt = logging.Formatter(logger_format)
if file:
file_handler = logging.FileHandler(file)
file_handler.setLevel(logger_level)
file_handler.setFormatter(fmt)
logger.addHandler(file_handler)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logger_level)
stream_handler.setFormatter(fmt)
logger.addHandler(stream_handler)
self.logger = logger
def debug(self,msg):
return self.logger.debug(msg)
def info(self,msg):
return self.logger.info(msg)
def warning(self,msg):
return self.logger.warning(msg)
def error(self,msg):
return self.logger.error(msg)
def critical(self,msg):
return self.logger.critical(msg)
这样,需要用到日志的时候,通过导入 my_logger 模块,使用 LoggerHandler 类里的 debug 和info 函数即可
|