logging库基础使用
前言:logging库是Python的日志管理软件,类似print但是比它更加强大,python自带的库。
logging库的日志级别
-
DEBUG:详细信息,调试信息。
-
INFO:确认一切按预期运行。
-
WARNING:发生了一些意外,或不久的将来会发生问题(如‘磁盘满了’)软件还是在正常工作。
-
ERROR:由于更严重的问题,软件已不能执行一些功能了。
-
CRITICAL:严重错误,表明软件已不能继续运行了。
默认情况下logging库会打印WANNING级别的日志信息。
日志等级 DEBUG<INFO<WARNING<ERROR<CRITICAL
只有级别高于或者等于日志级别的日志才会被输出,低于该等级的日志将会被丢弃。
比如设置 为 Info等级 那么 debug日志信息会被丢弃
日志库级别设置
# 如果logging不进行配置,默认WWRNING级别
logging.debug('这是一个BUG') # 不会输出到控制台
logging.info('这是一个通知') # 不会输出到控制台
logging.warning('这是一个警告') # 会输出到控制台
logging.errot('这是一个错误') # 会输出到控制台
logging.critical('这是一个致命错误') # 会输出到控制台
logging.basicConfig(**参数) 对日志完成一次性配置
- level 设置日志的级别
- format 设置日志的输出格式
# 模板如下所示
formatter='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'
logging.basicConfig(level=logging.WARNING,format=formatter)
★企业日志:输出到控制台和不同文件
logging的API | 说明 |
---|---|
getLogger(name) | 获得一个日志对象 |
StreamHandler() | 创建控制台对象(唯一) |
FileHandler(name, mode, encoding) | 创建文件对象(不唯一) |
setLevel() | 设置日志等级 |
setFormatter(formatter) | 设置日志输出格式 |
addHandler(对象) | 将控制台实例or文件实例添加到 logger 对象 |
需求一: 将程序运行日志分别给开发人员和测试人员,但是开发人员日志等级DEBUG,测试人员日志等级ERROR
# 创建 logger 对象
logger = logging.getLogger('test_logger')
# 设置日志输出等级总开关
logger.setLevel(logging.DEBUG)
- 创建的日志对象logger,就相当于print语句使用,不过它有5个级别
- 日志输出等级总开关,限定控制台实例和输入文件日志等级不能低于该级别
# 统一设置日志的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 创建控制台实例
sh = logging.StreamHandler()
# 设置控制台输出的日志级别
sh.setLevel(logging.DEBUG)
# 设置向控制台输出的日志格式
sh.setFormatter(formatter)
- 一个logger对象只有能有一个控制台实例,就是程序运行时的那个界面
# 创建供开发人员使用的日志devAPI.log
fh1 = logging.FileHandler('devApi.log',mode='a',encoding='utf-8')
# 设置向文件输出的日志级别
fh1.setLevel(logging.DEBUG)
# 设置向文件输出的日志格式
fh1.setFormatter(formatter)
# 创建供测试人员使用的日志testAPI.log
fh2 = logging.FileHandler('testAPI.log',mode='a',encoding='utf-8')
# 设置向文件输出的日志级别
fh2.setLevel(logging.DEBUG)
# 设置向文件输出的日志格式
fh2.setFormatter(formatter)
- devAPI.log,testAPI.log 文件不存在,会自动创建
- mode 参数设置为追加 append
- 为防止乱码, encoding 参数设置为 utf-8 编码格式
- 无论是控制台实例还是文件实例,三步设置:创建、等级、格式
# 加载控制台实例到 logger 对象中
logger.addHandler(sh)
# 加载文件实例到 logger 对象中
logger.addHandler(fh1)
logger.addHandler(fh2)
- 这里设置了一个控制台实例,二个文件实例
- 有了这个logger对象,使用时它会将日志同时输出到控制台和你指定的日志文件中保存,
需求二:API太多了,反复调用不方便,“封装成工具类”
LOG日志文件管理之后的项目大概率会被反复使用,没次使用都要在重新写一遍吗?不用,可以使用面向对象的思想将日志管理封装成工具类,之后使用直接调用工具类中的方法即可。
1,类名 LogUtil,类初始化代码放在 __ init __() 函数中;
2,对外提供内容/变量 变成属性 通过自定义功能函数 让外界调用即可
封装思想都是类似的:Java中类中私有化成员变量,提供set方法对属性设置get方法取得属性值;提供公共的方法供对象调用。
import logging
class LogUtil(object):
def __init__(self, name):
# 创建 logger 对象
self.__logger = logging.getLogger(name)
# 设置日志输出等级总开关
self.__logger.setLevel(logging.DEBUG)
# 创建控制台实例
sh = logging.StreamHandler()
'''
创建一个文件实例,如果 api.log 文件不存在,就会自动创建;
mode 参数设置为追加;另外为防止乱码, encoding 参数设置为 utf-8 编码格式
'''
fh1 = logging.FileHandler('devAPI.log', mode='a', encoding='utf-8')
# 创建供测试人员使用的日志testAPI.log
fh2 = logging.FileHandler('testAPI.log', mode='a', encoding='utf-8')
# 设置控制台输出的日志级别
sh.setLevel(logging.DEBUG)
# 设置向文件输出的日志级别
fh1.setLevel(logging.DEBUG)
fh2.setLevel(logging.ERROR)
# 统一设置日志的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 设置向控制台输出的日志格式
sh.setFormatter(formatter)
# 设置向文件输出的日志格式
fh1.setFormatter(formatter)
fh2.setFormatter(formatter)
# 加载控制台实例到 logger 对象中
self.__logger.addHandler(sh)
# 加载文件实例到 logger 对象中
self.__logger.addHandler(fh1)
self.__logger.addHandler(fh2)
def getLogger(self):
return self.__logger
# 测试
if __name__ == '__main__':
logger = LogUtil('test_log').getLogger()
logger.debug('BUG')
logger.error('错误')
-
封装一般是私有化成员变量,Python中私有化属性是在变量前面使用二个下划线self.__logger
-
实例化LogUtil对象时,会自动执行__ init__函数里的代码
需求三:日志文件存放固定位置并按日期存放
OS库API | 说明 |
---|---|
__ file__ | 获取当前文件所在路径(包括文件名) |
os.path.dirname(__ file__) | 获取当前文件所在文件夹 |
# 创建供开发人员使用的日志devAPI.log
fh1 = logging.FileHandler('devApi.log',mode='a',encoding='utf-8')
# 创建供测试人员使用的日志testAPI.log
fh2 = logging.FileHandler('testAPI.log',mode='a',encoding='utf-8')
- 此处只指定文件名字:devAPI.log, testAPI.log 默认当前路径
将日志文件存放在固定位置
如项目的logfiles包中。第一步先找到项目路径在拼接上’\log’就可以了
# 使用嵌套一个os.path.dirname就能实现上上层目录,具体几层需结合项目自行修改
project_path = os.path.dirname(os.path.dirname(__file__))
# 拼接成包路径
logfiles_path = project_path + os.sep + 'logfiles'
# 文件完整路径
path1 = os.path.join(logfiles_path, 'devAPI.log')
path2 = os.path.join(logfiles_path, 'testAPI.log')
- linux和windows系统文件路径分隔是不同的,使用 os.sep 来解决
- 日志存放的日志包需要提前创建好,日志文件名不存在会自动创建
将日志按天存放
-
需要引入时间API,time.localtime()
# 格式调整前 time.localtime() #time.struct_time(tm_year=2022, tm_mon=5, tm_mday=19, tm_hour=13, tm_min=57, tm_sec=27, tm_wday=3, tm_yday=139, tm_isdst=0) # 调整日期格式,注意格式大小写 time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) #2022-05-19 14:00:23
-
将日期作为文件名
filename = '{}.log'.format(time.strftime('%Y-%m-%d', time.localtime())) file_path = os.path.join(logfiles_path, filename)