一、logging介绍
日志的作用
- 程序调试
- 了解程序运行是否正常
- 故障分析与问题定位
- 用户行为分析
日志等级
- debug–最详细的日志信息,典型应用场景是问题诊断
- info–信息详细城府仅次于debug,通常只记录关键节点,用于确认都是按照我们预期的那样进行工作的
- warning–当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
- error–由于一个更严重的问题导致某些功能不能正常运行时记录的信息
- critical-- 当发生严重错误,导致应用程序不能继续运行时记录的信息
logging模块的使用
- 第一种方式时使用logging提供的模块级别函数,使用很简单
logging.debug('debug')
,想要控制输出的等级信息等用到logging.basicConfig(level=logging.INFO)
- 第二种方式时使用logging日志系统的四大组件,适用于项目封装
logging模块的四大组件
- loggers–提供应用程序代码直接使用的接口
- handlers–句柄,用于将日志信息发送到指定的目标位置(控制台或者文件)
- filters–提供更细粒度的日志过滤功能,用于决定哪些日志将会被输出(其他的日志记录将会被忽略)
- formatters–用于控制日志信息的最终输出格式(包含日期、用户名称、信息等)
logging使用非常简单,使用basicConfig()方法就能满足基本的使用需要
二、formatters控制日志输出格式
logging.basicConfig()函数说明
参数名 | 描述 |
---|---|
filename | 指定日志输出目标文件的文件名,指定该设置项后日志信息就不会输出到控制台了,输出到文件 |
filemode | 指定日志文件的打开模式,默认是‘-a’,需要注意的是,该选项要在filename指定时才有效 |
format | 指定日志格式字符串,即指定日志输出时所包含的字段信息以及他们的顺序 |
datefmt | 指定日期/时间格式,需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效 |
style | python3.2中新增添加的配置项,指定format格式字符串的风格,可取值为‘%’用于print样式、‘{‘用于str.format()和’$'用于string,默认 ‘%’ |
level | 指定日志器的日志级别 |
stream | 指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream,需要说明的是stream和filename不能同时提供,否则会引发ValueError异常 |
handlers | python3.3中新添加的配置项。该选项如果被指定,他应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常 |
format的格式
字段/属性名称 | 使用格式 | 操作 |
---|---|---|
asctime | %(asctime)s | 日志时间发生的时间-人类可读时间,如:2022-02-13 10:11:50,896 |
created | %(created)f | 日志时间发生的时间-时间戳,即当前时间调用time.time()函数返回的值 |
relativeCreated | %(relativeCreated)d | 日志时间发生的时间相对于logging模块加载时间的相对毫秒数 |
msecs | %(msecs)d | 日志事件发生的毫秒部分 |
name | %(name)s | 所使用的日志器的名称,默认是‘root’,因为默认使用的rootLogger |
levelno | %(levelno)s | 该日志记录的数字形式的日志级别(10,20,30,40,50) |
levelname | %(levelname)s | 该日志记录的文字形式的日志级别(‘DEBUG’,‘INFO’,‘WARNING’,’‘ERROR’,‘CRITICAL’) |
pathname | %(pathname)s | 调用日志记录函数的源码文件的全路径 |
filename | %(filename)s | pathname的文件部分,包含文件后缀 |
module | %(module)s | filename的名称部分,不包含后缀 |
lineno | %(lineno)d | 调用日志记录函数的源代码所在的行号 |
funcName | %(funcName)s | 调用日志记录函数的函数名 |
thread | %(thread)d | 线程id |
threadName | %(threadName)s | 线程名称 |
process | %(process)d | 进程id |
message | %(message)s | 日志记录的文本内容,通过msg % args 计算得到的 |
实例
my_format = '%(asctime)s-%(filename)s-%(lineno)d'
logging.basicConfig(
filename='my.log',
level=logging.INFO,
format=my_format
)
logging.info('info')
logging.debug('debug')
logging.warning('warning')
结果是输出一个日志文件,保存在当前文件夹下
三、logging的四大组件-handler
logger类
使用工厂方法返回一个logger事例
logger = logging.getLogger(name='mylogger')
指定name,返回一个名称为mylogger的logger事例,未指定名称默认是root,即根logger。
方法 | 描述 |
---|---|
logger.setLevel() | 设置日志器将会处理的日志消息的最低级别 |
logger.addHandler()和logger.removeHandler() | 为该logger对象添加和移除一个handler对象 |
logger.addFilter()和logger.removeHandler() | 为该logger对象添加和移除一个filter对象 |
logger.debug()、logger.info()、logger.warning()、logger.error()、logger.critical() | 创建一个与他们的方法名对应等级的日志记录 |
logger.exception() | 创建一个类似于logger.error()的日志信息 |
logger.log() | 需要获取一个明确的日志level参数来创建一个日志记录 |
handler
控制日志信息的输出地,可以是控制台,也可以是文件
handler类
方法 | 描述 |
---|---|
handler.setLevel() | 设置handler将会处理的日志消息的最低严重级别 |
handler.addFilter() | 为handler设置一个格式器对象 |
handler.removeFilter() | 为handler添加和删除一个过滤器对象 |
handler是通过logging.handlers模块定义的某种类型handler
handler相关子类
handler | 描述 |
---|---|
logging.StreamHandler | 将日志消息发送输出到stream,如std.out,std.err或任何file-like对象 |
logging.FileHandler | 将日志消息发送到磁盘文件,默认情况下文件大小会无限增长 |
logging.handlers.RotatingFileHandler | 将日志消息发送到磁盘文件,并支持日志文件按大小切割 |
logging.handlers.TimedRotatingFileHandler | 将日志消息发送到磁盘文件,并支持日志文件按时间切割 |
logging.handlers.HTTPHandler | 将日志消息以GET或POST的方式发送给一个HTTP服务器 |
logging.handlers.SMTPHandler | 将日志i消息发送给一个指定的email地址 |
logging.NullHandler | 该handler事例会忽略error messages,通常被想使用logging的library开发者使用来避免‘No handlers could be found for logger XXX’信息的出现 |
实例
import datetime
import logging
import logging.handlers
logger = logging.getLogger(name='mylogger') #定义一个日志对象,名称是mylogger,不写的话返回root
logger.setLevel(logging.INFO) #设置logger等级
rf_handler = logging.handlers.RotatingFileHandler('all.log')
'''
when -什么时间触发
interval -间隔时长
backupCount -备份多少份
'''
rf_handler.setFormatter(logging.Formatter("%(asctime)s-%(filename)s-%(lineno)d-%(message)s"))
error_handler = logging.FileHandler('error.log')
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(logging.Formatter("%(asctime)s-%(levelname)s-%(filename)s[%(lineno)d-%(message)s]"))
logger.addHandler(rf_handler)
logger.addHandler(error_handler)
logger.debug('debug message')
logger.info('info message')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical message')
可以将上面实例直接封装成一个工具,直接调用
将日志输出到指定logs文件夹需要用到os模块
path1 = os.path.abspath(__file__) # 返回绝对路径,/Users/admin/Documents/files/python/selenium_project/testcase/log/test02.py
path2 = os.path.dirname(__file__) #返回文件路径,/Users/admin/Documents/files/python/selenium_project/testcase/log
path = str(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))+'/logs/' #一直后退,再拼接logs,再生成all.log文件
rf_handler = logging.handlers.RotatingFileHandler(path+'all.log')