也就是日记,程序运行过程中产生的信息,程序如何运行的信息(什么时间做了什么)
日志即可以在终端中显示,也可以直接到文件当中显示
日志的作用:方便定位,记录
日志包含的信息:日期,等级,信息
等级:
-- NOSET 0 等于没写
-- debug 10 调试信息,
-- info 20 主体功能信息,如日报,做了什么工作
-- warning 30 警告信息,如交警警告
-- error 40 错误信息,如抢红灯,犯错c
-- critical 50 严重错误信息,如打劫
日志有两种记录方法:
一种是需要安装第三方库,loguru
一种是python自带的,直接导入就能用,logging
使用步骤:
第一步:
使用之前若未安装过,要先进行安装,按之前的两种方法安装不上,就用此命令安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ --upgrade loguru
第二步:
导入 from loguru import logger
from loguru import logger
logger.info('这是一个正常的日志,我正在执行主程序')
logger.warning('这是一个警告信息')
logger.error('这是错误信息')
运行结果:
记录程序运行的日志:
1. logger.info()记录步骤
2. logger.error()记录错误
在一项目中如何使用呢?如下
import unittest # 导入unittest
from loguru import logger
def login(username=None, password=None):
if username is None or password is None:
return {"code": "400", "msg": "用户名或密码为空"}
if username == 'yuz' and password == '123':
return {"code": "200", "msg": "登录成功"}
return {"code": "300", "msg": "用户名或密码错误"}
# 添加日志文件
logger.add(sink='demo_log.log', encoding='utf-8')
class TestLogin(unittest.TestCase):
def test_login_1(self):
username = 'li'
password = '123'
expected = {"code": "300", "msg": "用户名或密码错误"}
logger.info('正在执行测试用1...')
actual = login(username, password)
self.assertEqual(expected, actual)
logger.info('测试用例1执行完毕')
def test_login_2(self):
username = 'yuz'
password = '123'
expected = {"code": "300", "msg": "用户名或密码错误"}
logger.info('正在执行测试用2...')
actual = login(username, password)
try:
self.assertEqual(expected, actual)
except AssertionError as e:
# 在日志中记录断言异常
logger.error('测试用例2失败')
# 捕获异常后,一定要手动抛出
raise e
logger.info('测试用例2执行完毕')
def test_login_3(self):
username = None
password = '123'
expected = {"code": "400", "msg": "用户名或密码为空"}
logger.info('正在执行测试用3...')
actual = login(username, password)
self.assertEqual(expected, actual)
logger.info('测试用例3执行完毕')
运行结果:
info可以写在任何一行进行记录,error要放在可能出错误的地方,也就是断言的地方
运行后会自动生成一个demo_log.log文件
添加日志文件的参数修改成
logger.add(sink='demo_log.log', encoding='utf-8',level='ERROR')
demo_log.log文件只显示等级是警告以上的日志,也就是ERROR,CRITICAL
添加日志文件的参数修改成
logger.add(sink='demo_log.log', encoding='utf-8', rotation='10 B')
以10B的大小来分隔log文件,会自动生成文件
roation的参数有:
rotation = '500 MB' 按文件的大小生成文件
rotation = '12:00' 按文件的时间每天12点生成文件
rotation = '1 week' 按文件的时间1周生成文件
rotation = '1 days' 按文件的时间1天生成文件
添加日志文件的参数修改成
logger.add(sink='demo_log.log', compression='zip')
生成压缩文件
logging不需要安装,直接导入:import logging,就可以使用
import logging
logging.info('这是一个正常信息')
logging.error('这是一个错误信息')
运行结果:
从运行结果上可以看到,只输入了error的日志信息,logging如果不去代码编写,默认是不显示info级别的内容
下面我们就看一下如何去编写代码,来进行记录日志:
import logging
'''
1.得到一个日志收集器,logger
2.打比方:写日记,需要日记本,笔,写的内容
logger 这支笔,要专门去记录py44这样的事项,也就是这支笔叫什么笔的意思
也就是PY44这支笔
'''
logger = logging.getLogger('PY44')
# 设置笔的级别
logger.setLevel('INFO')
# 显示的东西 Handler:笔记本,黑板,墙壁
# 默认笔记本:StreamHandler,输出到控制台
handler = logging.StreamHandler()
# 设置笔记本的级别
handler.setLevel('INFO')
# 设置格式
fmt = logging.Formatter(style='{', fmt='{asctime}:{name}:{levelname}:{filename}:{lineno}:{message}')
handler.setFormatter(fmt)
# 把笔记本添加到笔上
logger.addHandler(handler)
# 另外一个handler,写到日志文件里
file_handler = logging.FileHandler('demo.log', encoding='utf-8')
# 设置handler的级别
file_handler.setLevel('ERROR')
# 设置handler的格式
fh_fmt = logging.Formatter(fmt='%(asctime)s---%(name)s---%(levelname)s---%(message)s')
file_handler.setFormatter(fh_fmt)
# 把handler添加到笔上
logger.addHandler(file_handler)
# 记录日志信息
logger.info('这是正常信息')
logger.error('这是错误信息')
运行结果:
从运行结果上可以看出来
-- demo.log只打印出一条日志信息,而控制台打印出两条日志信息
因为file_handler.setLevel('ERROR')的等级设置是ERROR
而handler.setLevel('INFO')的等级设置的是INFO
-- demo.log与控制台打印的日志信息不一样,因为格式设置的问题,这两行代码的原因
fmt = logging.Formatter(style='{', fmt='{asctime}:{name}:{levelname}:{filename}:{lineno}:{message}')
写了style,就不用再写%和s了
fh_fmt = logging.Formatter(fmt='%(asctime)s---%(name)s---%(levelname)s---%(message)s')
日志信息的内容是可以随便设置的,具体代表的意思可参考官网publogging --- Python 的日志记录工具 — Python 3.10.0 文档
注意:
1、格式设置时,fmt= 是固定写法,不能修改否则会报错
2、等级设置
笔(logger)跟显示的地方(handler,file_handler)同时设置相同等级时,显示一致
import logging
logger = logging.getLogger('PY44')
# 设置笔的等级
logger.setLevel('INFO')
handler = logging.StreamHandler()
# 设置显示地方的等级
handler.setLevel('INFO')
logger.addHandler(handler)
# 记录日志信息
logger.info('这是正常信息')
logger.error('这是错误信息')
logger.critical('这是严重错误信息')
运行结果:
这是正常信息
这是错误信息
这是严重错误信息
笔(logger)跟显示的地方(handler,file_handler)同时设置不相同等级时,按级别高的显示,默认不写时,日志信息显示等级ERROR级别以上
import logging
logger = logging.getLogger('PY44')
# 设置笔的等级
logger.setLevel('INFO')
handler = logging.StreamHandler()
# 设置显示地方的等级
handler.setLevel('ERROR')
logger.addHandler(handler)
# 记录日志信息
logger.info('这是正常信息')
logger.error('这是错误信息')
logger.critical('这是严重错误信息')
import logging
logger = logging.getLogger('PY44')
# 设置笔的等级
logger.setLevel('ERROR')
handler = logging.StreamHandler()
# 设置显示地方的等级
handler.setLevel('INFO')
logger.addHandler(handler)
# 记录日志信息
logger.info('这是正常信息')
logger.error('这是错误信息')
logger.critical('这是严重错误信息')
运行结果:(两段代码的运行结果是一致的)
这是错误信息
这是严重错误信息
实际工作中,不用每次用都写一遍,封装成一个函数做为一个模块,使用时直接导入模块使用
封装函数:
import logging
def get_log(name='py44',
level='INFO',
fmt = '%(asctime)s---%(name)s---%(levelname)s---%(message)s',
file_name='demo.log'):
logger = logging.getLogger(name)
# 设置笔的级别
logger.setLevel(level)
# 显示的东西 Handler:笔记本,黑板,墙壁
# 默认笔记本:StreamHandler,输出到控制台
handler = logging.StreamHandler()
# 设置笔记本的级别
handler.setLevel(level)
# 设置格式
# 注意变量的命名不要跟fmt重复
had_fmt = logging.Formatter(fmt=fmt)
handler.setFormatter(had_fmt)
# 把笔记本添加到笔上
logger.addHandler(handler)
# 另外一个handler,写到日志文件里
file_handler = logging.FileHandler(file_name, encoding='utf-8')
# 设置handler的级别
file_handler.setLevel(level)
# 设置handler的格式
fh_fmt = logging.Formatter(fmt=fmt)
file_handler.setFormatter(fh_fmt)
# 把handler添加到笔上
logger.addHandler(file_handler)
return logger
logger = get_log()
logger.info('正常信息')
logger.error('错误信息')
运行结果: