python 日志打印
参考https://www.cnblogs.com/yangliheng/p/6058436.html
1:四个主要类,使用官方文档中的概括:
logger 提供了应用程序可以直接使用的接口;
handler 将(logger创建的)日志记录发送到合适的目的输出;
filter 提供了细度设备来决定输出哪条日志记录;用处不太大
formatter 决定日志记录的最终输出格式
2:模块级函数
logging.getLogger([name]): #返回一个logger对象,如果没有指定名字将返回root logger,最常用
logging.basicConfig(): #给logger对象的配置管理函数 ,不常用
logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical(): #logger的日志级别
3:logging模块的api
1)logging.getLogger([name])
返回一个logger实例,如果没有指定name,返回root logger。只要name相同,返回的logger实例都是同一个而且只有一个,即name和logger实例是一一对
应的。这意味着,无需把logger实例在各个模块中传递。只要知道name,就能得到同一个logger实例
2)logger.setLevel(lvl)——设置logger的level,
level有以下几个级别:
NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL
不同日志级别对应的数字对照
级别 数值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
如果把logger的级别设置为INFO, 那么小于INFO级别的日志都不输出, 大于等于INFO级别的日志都输出。也就意味着同一个logger实例,如果多个地方调用,会
出现很多重复的日志
3)logger.addHandler(hd)—— logger雇佣handler来帮它处理日志
handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输
出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
handler主要有以下几种:
logging.StreamHandler: #日志输出到流即控制台,可以是sys.stderr、sys.stdout
logging.FileHandler: #日志输出到文件
logging.handlers.RotatingFileHandler #日志输出到文件,并按照设定的日志文件大小切割
logging.handlers.TimedRotatingFileHandler #日志输出到文件,并按设定的时间切割日志文件
logging.handlers.SocketHandler: #远程输出日志到TCP/IP sockets
logging.handlers.DatagramHandler: #远程输出日志到UDP sockets
logging.handlers.SMTPHandler: #远程输出日志到邮件地址
logging.handlers.SysLogHandler: #日志输出到syslog
logging.handlers.NTEventLogHandler: #远程输出日志到Windows NT/2000/XP的事件日志
logging.handlers.MemoryHandler: #日志输出到内存中的制定buffer
由于StreamHandler和FileHandler是常用的日志处理方式,所以直接包含在logging模块中,而其他方式则包含在logging.handlers模块中,
handle常见调用
Handler.setLevel(lel) #指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter() #给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):#新增或删除一个filter对象
4:常用配制
关于logging.basicConfig函数的常用配置:
filename: 指定日志文件名
filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING,即warning及级别更高的日志才输出
stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被
忽略
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
%(name)s 打印logger名,默认为root
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(message)s: 打印日志信息
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
# 项目目录 basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取根目录路径 # 日志配置 logdir = os.path.join(basedir, 'log') logpath =os.path.join(logdir, 'apiall.log') error =os.path.join(logdir, 'apierror.log') logger = logging.getLogger('apiteststudy')#logger:日志对象,logging模块中最基础的对象, # 用logging.getLogger(name)方法进行初始化,name可以不填。通常logger的名字我们对应模块名,如聊天模块、数据库模块、验证模块等。 # 打印debug 以上全部信息 logger.setLevel(logging.DEBUG)#logger对象常用方法setLevel:设置日志等级,一旦设置了日志等级,则调用比等级低的日志记录函数则不会输出 datafmt = "%Y-%m-%d %H:%M:%S" #定义日志输出格式formatter fm = logging.Formatter(fmt='%(asctime)s %(name)-s %(module)-s[line:%(lineno)d] %(levelname)-s -- %(message)s',datefmt=datafmt) # 创建一个handler,用于输出到控制台,一般不用 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) #再创建一个handler,用于写入日志文件,只输出debug级别以上的日志,并调用定义的输出格式 fh = logging.handlers.TimedRotatingFileHandler(logpath, when='D', interval=1, backupCount=5,atTime=datetime.time(0, 0, 0, 0),encoding='utf-8') # interval是时间间隔,backupCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种: # S 秒、 M 分 小时、D 天、W 每星期(interval==0时代表星期一)、midnight 每天凌晨 # fh = logging.FileHandler(logpath, encoding='utf-8') # fh.setLevel(logging.DEBUG) fh.setFormatter(fm) ch.setFormatter(fm) logger.addHandler(fh) #打印到文件 logger.addHandler(ch) #打印到控制台 logging.getLogger("requests").setLevel(logging.WARNING) # # 打印错误信息 f_handler = logging.handlers.TimedRotatingFileHandler(error, when='S', interval=1, backupCount=5,atTime=datetime.time(0, 0, 0, 0),encoding='utf-8') f_handler.setLevel(logging.ERROR) datafmt = "%Y-%m-%d %H:%M:%S" fm = logging.Formatter(fmt='%(asctime)s %(name)-s %(module)-s[line:%(lineno)d] %(levelname)-s -- %(message)s',datefmt=datafmt) f_handler.setFormatter(fm) logger.addHandler(f_handler) if __name__ == "__main__": logger.info('this is test') print("根目录:{}".format(basedir))
5.调用
import logging
import logging.config
logging.config.fileConfig("logger.conf")
logger = logging.getLogger("example01")
logger.debug('This is debug message')
logger.info('This is info message')
logger.warning('This is warning message')
from config.config import logger if type(res)==dict: try: response_status_code=res['code'] except : response_status_code = None if response_status_code in [0, 200]: logger.info("接口正常:接口返回状态码==200|0") # logger.info("响应内容:%s" % res.json()) logger.info("响应内容:%s" % res) # result = res.json()["msg"] # result=res.json() result = res # self.assertEqual(result, 'success', msg='断言msg是否等于success') logger.info('实际结果:{0} 期望结果:{1}'.format(result, 'success')) # 带关键字 # print('接口响应:{0}'.format(res.json())) print('接口响应:{0}'.format(res)) print(('实际结果:{0} 期望结果:{1}'.format(result, 'success'))) else: logger.error("接口错误:接口失败返回状态码!=200") else: response_status_code=res.status_code#返回结果为HttpResponse对象时才可用.status_code if response_status_code in [0,200]: logger.info("接口正常:接口返回状态码==200|0") # logger.info("响应内容:%s" % res.text) # result = res.json()["msg"] result=res.text # self.assertEqual(result, 'success', msg='断言msg是否等于success') logger.info('实际结果:{0} 期望结果:{1}'.format(result, 'success')) # 带关键字 # print('接口响应:{0}'.format(res.text)) print(('实际结果:{0} 期望结果:{1}'.format(result, 'success'))) else: logger.error("接口错误:接口失败返回状态码!=200")