1.日志
用于记录系统运行时的信息,对一个事件的记录,也称为log
1.1日志的作用
1.调试程序
2.了解系统程序运行的情况,是否正常
3.系统程序运行故障分析与问题定位
4.用来做用户行为分析和数据统计
1.2 日志级别
日志信息的优先级、重要性、严重程度
常见日志级别
日志级别 | 描述 |
---|---|
DEBUG | 调试级别,打印非常详细的日志信息,通常用于对代码的调试 |
INFO | 信息级别,打印一般的日志信息,突出强调程序的运行过程 |
WARNING | 警告级别,打印警告日志信息,表明会出现潜在错误的情形,一般不影响软件的正常使用 |
ERROR | 错误级别,打印错误异常信息,该级别的错误可能会导致系统的一些功能无法正常使用 |
CRITICAL | 严重错误级别,一个严重的错误,这表明系统可能无法继续运行 |
说明:
1.严重级别:DEBUG<INFO<WARNING<ERROR<CRITICAL
2.当为程序指定一个日志级别后,程序会记录所有日志级别大于或等于指定日志级别的日志信息,而不是仅仅记录指定级别的日志信息
3.一般建议,只使用:DEBUG,INFO,WARNING,ERROR 这四个级别
2.日志的基本用法
2.1 logging模块
python中有一个标准库模块logging可以直接记录日志
2.1.1基本用法
import logging
#设置日志级别 大写DEBUG 默认级别从WARNING开始
logging.basicConfig(level=logging.DEBUG)
logging.debug("这是一个debug")
logging.info("这是一个info")
logging.warning("这是一个warning")
logging.error("这是一个error")
logging.critical("这是一个critical")
2.1.2设置日志格式
format参数中可能用到的格式化信息
占位符 | 描述 |
---|---|
%(name)s | Logger的名字 |
%(levelno)s | 数字形式的日志级别 |
%(levelname)s | 文件形式的额日志级别 |
%(pathname)s | 调用日志输出函数的模块的完整路径名 可能没有 |
%(filename)s | 调用日志输出函数的模块的文件名 |
%(module)s | 调用日志输出函数的模块名 |
%(funcName)s | 调用日志输出函数的函数名 |
%(lineno)d | 调用日志输出函数的语句所在的代码行 |
%(created)f | 当前时间 ,用UNIX标准的表示时间的浮点数表示 |
%(relative Created)d | 输出日志信息时的 自Logger创建以来的毫秒数 |
%(asctime)s | 字符串形式的当前时间,默认格式“2021-07-25 16:54:54,896” |
%(thread)d | 线程ID,可能没有 |
%(threadName)s | 线程名,可能没有 |
%(process)d | 进程ID,可能没有 |
import logging
fm='%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] -%(message)s'
logging.basicConfig(level=logging.INFO,format=fm)
logging.debug("调试")
logging.info("信息")
logging.warning("警告")
logging.error("错误")
2.1.3 将日志信息输出到文件中
默认情况下python的logging模块将日志打印到了标准输出中(控制台)
解决方法“:
logging.basicConfig(filename=‘a.log’)
import logging
# 设置日志格式
fm = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] -%(message)s'
#设置日志保存到指定文件
logging.basicConfig(level=logging.INFO, format=fm,filename='../log/test02.log')
logging.debug("调试")
logging.info("信息")
logging.warning("警告")
logging.error("错误")
解决中文乱码的问题:
点击basicConfig源代码,添加encoding="utf-8"即可
if filename:
h = FileHandler(filename, mode,encoding="utf-8")
如图所示:
2.3 日志的高级用法
2.3.1 logging日志模块四大组件
组件之间的关系
- 日志器(logger)需要通过处理器(handler)将日志信息输出到目标位置,如:文件,sys.sltout,网络等
- 不同的处理器(handler)可以将日志输出到不同的位置
- 日志器(logger)可以设置多个处理器(handler)将同一条日志记录到不同的位置
- 每个处理器(handler)都可以设置自己的格式器(fomatter)实现同一条日志以不同的格式输出到不同的地方
- 每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志
简单的说,日志器是入口,真正干活的是处理器,处理器还可以通过过滤器和格式器对要输出的日志内容做过滤和格式化等处理操作
2.3.2Logger常用的方法
logger.setLevel(): 设置日志将会处理的日志消息的最低严重程度
logger.addHandler():为该logger对象添加一个handler对象
logger.addFilter():为该logger对象添加一个filter对象
2.3.3 Handler类
Handler对象的作用是将消息分别发到handler指定的位置,比如:控制台,文件,网络,邮件等。Logger对象可以通过addHandler()方法为自己添加多个handler对象
如何创建Handler对象
在程序中不应该直接实例化和使用handler实例,因为Handler是一个基类,他只定义了Handler应该有的接口,应该使用Handler实现类来创建对象,logging中内置的常用的Handler包括:
Handler | 描述 |
---|---|
logging.StreamHandler | 将日志消息发送到输出到Stream,如:std.out,std.err或任何file-like对象 |
logging.FileHandler | 将日志消息发送到磁盘文件,默认情况下文件大小会无限增长 |
logging.handlers.RotatingFileHandler | 将日志消息发送到磁盘文件,并支持日志文件按大小切割 |
logging.handlers.TimeRotatingFileHandler | 将日志消息发送到磁盘文件,并支持日志文件按时间切割 |
logging.handlers.HTTPHandler | 将日志消息以GET,POST的方式发送给一个HTTP服务器 |
"""
目标:学习logging底层,模块实现
1.logger.StreamHandler
"""
import logging
# 获取logger
logger = logging.getLogger()
# 设置级别
logger.setLevel(logging.INFO)
#获取控制台处理器
sh=logging.StreamHandler()
#到文件 根据时间
# sts=logging.StringTemplateStyle()
#将处理器添加到logger中
logger.addHandler(sh)
# logger.addHandler(sts)
# 输出信息
logger.info("info")
logger.debug("debug")
"""
目标:学习logging底层,模块实现
1.logger.handlers.TimedRotatingFileHandler
"""
#import logging
'''
注意:导入import logging.handlers
handlers为模块名称
'''
import logging.handlers
# 获取logger
logger = logging.getLogger()
# 设置级别
logger.setLevel(logging.INFO)
#获取控制台处理器
sh=logging.StreamHandler()
#到文件 根据时间
th=logging.handlers.TimedRotatingFileHandler(filename="../log/logtime.log",
when="M",
interval=1,
backupCount=3)
#将控制台处理器添加到Logger
logger.addHandler(th)
# 输出信息
logger.info("info")
logger.debug("debug")
Handler常用的方法
方法 | 描述 |
---|---|
handler.setLevel() | 设置handler将会处理的日志消息的最低严重级别 |
handler.sedFormatter() | 为handler设置一个格式器对象 |
hanler.addFilter() | 为handler添加一个过滤器对象 |
2.3.4Formatter类
Formatter对象用于配置日志信息的格式
如何创建Formatter对象
formatter=logging.Formatter(fmt=None,datefmt=None,style="%")
fmt:指定消息格式化字符串,如果不指定该参数则默认使用message的原始值
datefmt:指定日期格式字符串,如果不指定该参数则默认使用“%Y-%m-%d %H:%M:%S”
style:python3.2新增的参数,可取值为“%”,“{”和“$“,如果不指定该参数则默认使用‘%’
"""
目标:学习logging底层,模块实现
1.logger.handlers.TimedRotatingFileHandler
"""
# import logging
from time import sleep
'''
注意:导入import logging.handlers
handlers为模块名称
'''
import logging.handlers
# 获取logger
# logger = logging.getLogger()
# 修改名称
logger = logging.getLogger("admin")
# 设置级别
logger.setLevel(logging.INFO)
# 获取控制台处理器
sh = logging.StreamHandler()
# 到文件 根据时间
th = logging.handlers.TimedRotatingFileHandler(filename="../log/logtime.log",
when="S",
interval=1,
backupCount=3)
# 添加格式器
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] -%(message)s'
fm = logging.Formatter(fmt)
# 将格式器添加到处理器中
sh.setFormatter(fm)
th.setFormatter(fm)
# 将控制台处理器添加到Logger
logger.addHandler(sh)
logger.addHandler(th)
# 测试
# while True:
# sleep(3)
# #输出信息
# logger.info("info")
# logger.debug("debug")
logger.info("info")
logger.debug("debug")
logger封装
# 导包
import logging.handlers
def get_logger():
# 获取 日志器 (日志器里可以添加多个处理器)
logger = logging.getLogger()
# 设置日志器级别
logger.setLevel(logging.INFO)
# 获取处理器 控制台
sh = logging.StreamHandler()
# 获取处理器 文件 以时间分割
th = logging.handlers.TimedRotatingFileHandler(filename="../log/log05.log",
when="midnight",
interval=1,
backupCount=30,
encoding="UTF-8"
)
# 设置格式器
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] -%(message)s'
fm = logging.Formatter(fmt)
# 将格式器设置到处理器上 控制台
sh.setFormatter(fm)
# 将格式器设置到处理器上 文件
th.setFormatter(fm)
# 将处理器添加到日志器
logger.addHandler(sh)
logger.addHandler(th)
return logger
if __name__ == "__main__":
logger=get_logger()
logger.info("info信息")
logger.debug("debug调试")
logger.warning("warning警告")
logger.error("error错误")
进行代码封装 单例封装
# 导包
import logging.handlers
class GetLogger:
logger = None
@classmethod
def get_logger(cls):
if cls.logger is None:
# 获取 日志器 (日志器里可以添加多个处理器)
cls.logger = logging.getLogger()
# 设置日志器级别
cls.logger.setLevel(logging.INFO)
# 获取处理器 控制台
sh = logging.StreamHandler()
# 获取处理器 文件 以时间分割
th = logging.handlers.TimedRotatingFileHandler(filename="../log/log05.log",
when="midnight",
interval=1,
backupCount=30,
encoding="UTF-8"
)
# 设置格式器
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] -%(message)s'
fm = logging.Formatter(fmt)
# 将格式器设置到处理器上 控制台
sh.setFormatter(fm)
# 将格式器设置到处理器上 文件
th.setFormatter(fm)
# 将处理器添加到日志器
cls.logger.addHandler(sh)
cls.logger.addHandler(th)
return cls.logger
if __name__ == "__main__":
logger = GetLogger().get_logger()
logger.info("info信息")
logger.debug("debug调试")
logger.warning("warning警告")
logger.error("error错误")