前言
- 现在要求将错误日志写入日志文件,通过查询日志文件的方式,可以查看最新用例的执行情况,并快速定位问题
- 使用print能够将一些错误信息输出在屏幕上,但是无法写入在文件中
- 本篇博客介绍如何使用logging库实现日志输出
logging库
logging日志级别
debug info warning error critical
logging简单示例
- loggin默认只输出 级别为warning error critical的日志
- logging.basicConfig(**kwargs) 控制着logging的行为,其中level=[]控制日志输出等级
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug('这是一个debug级别的信息,一般用来打印一些调试信息,级别最低')
logging.info('这是一个info级别的信息,一般用来打印一些正常的操作信息')
logging.warning('这是一个warning级别的信息')
logging.error('这是一个error级别的信息')
logging.critical('这是一个critical级别的信息,一般用来打印一些致命的错误信息,等级最高')
logging.basicConfig(**kwargs)参数
- filename:指定日志文件名
- filemode:和file函数意义相同,指定日志文件的打开模式,'w'或者'a'
- format:指定输出的格式和内容,format可以输出很多有用的信息
'''
formatter = logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s-日志信息:%(message)s')
%(name)s logger的名字(常用)
%(levelno)s 数字形式的日志级别
%levelname()s 文本形式的日志级别(常用)
%pathname()s 调用日志输出函数模块的完整路径名,可能没有(常用)
%filename()s 调用日志输出函数的文件名(常用)
%(module)s 调用日志输出函数的函数名
%(funcName)s 调用日志输出函数语句的
%(lineno)d 调用日志输出函数语句的代码行
%(created)f 当前时间,用unix标准表示
%(relativeCreated)d 输出日志信息时间,自logger创建以来的毫秒数
%(asctime)s 字符串形式的当前时间,默认格式‘2000-01-01 10:00:00,100’
%(thread)d 线程ID,可能没有
%(threadName)s 线程名,可能没有
%(process)d 进程ID,可能没有
%(message)s 用户输出的消息(常用)
'''
- datefmt:指定时间格式,同
time.strftime()
- level:设置日志级别,默认为
logging.WARNNING
- stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略
haddler种类
logging是通过addHandler添加主处理对象,haddler种类有:
'''
handler名称:位置;作用
StreamHandler:logging.StreamHandler 日志输出到流,可以是sys.stderr,sys.stdout或者文件
FileHandler:logging.FileHandler 日志输出到文件
BaseRotatingHandler:logging.handlers.BaseRotatingHandler 基本的日志回滚方式
RotatingHandler:logging.handlers.RotatingHandler 日志回滚方式,支持日志文件最大数量和日志文件回滚
TimeRotatingHandler:logging.handlers.TimeRotatingHandler 日志回滚方式,在一定时间区域内回滚日志文件
SocketHandler:logging.handlers.SocketHandler 远程输出日志到TCP/IP sockets
DatagramHandler:logging.handlers.DatagramHandler 远程输出日志到UDP sockets
SMTPHandler:logging.handlers.SMTPHandler 远程输出日志到邮件地址
SysLogHandler:logging.handlers.SysLogHandler 日志输出到syslog
NTEventLogHandler:logging.handlers.NTEventLogHandler 远程输出日志到Windows NT/2000/XP的事件日志
MemoryHandler:logging.handlers.MemoryHandler 日志输出到内存中的指定buffer
HTTPHandler:logging.handlers.HTTPHandler 通过"GET"或者"POST"远程输出到HTTP服务器
'''
输出日志在控制台和文本中示例
# File : test.py
# IDE : PyCharm
import sys
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.DEBUG) # 输出等级
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 输出格式
handler = logging.FileHandler("log.txt") # 文本输出
handler.setFormatter(formatter)
console = logging.StreamHandler(sys.stdout) # 控制台输出
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
if __name__ == '__main__':
logger.info("这是一条info级别信息")
logger.debug("这是一条debug级别信息")
logger.warning("这是一条warning级别信息")
执行结果
封装日志处理
# File : logger_operation.py
# IDE : PyCharm
import os
import sys
import logging
from time import strftime
class Logger():
def __init__(self):
# 日志格式
custom_format = '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'
# 日期格式
date_format = '%a, %d %b %Y %H:%M:%S'
# 日志路径
log_path = os.path.abspath('.') + '/logs/'
self._logger = logging.getLogger() # 实例化
self.filename = '{0}{1}.log'.format(log_path, strftime("%Y-%m-%d")) # 日志文件名
self.formatter = logging.Formatter(fmt=custom_format, datefmt=date_format)
self._logger.addHandler(self._get_file_handler(self.filename))
self._logger.addHandler(self._get_console_handler())
self._logger.setLevel(logging.INFO) # 默认等级
def _get_file_handler(self, filename):
'''输出到日志文件'''
filehandler = logging.FileHandler(filename, encoding="utf-8")
filehandler.setFormatter(self.formatter)
return filehandler
def _get_console_handler(self):
'''输出到控制台'''
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(self.formatter)
return console_handler
@property
def logger(self):
return self._logger
if __name__ == '__main__':
import datetime
logging=Logger().logger
logging.info(u"{}:执行xxx用例".format(datetime.datetime.now()))
总结
- 本篇博客只实现了logging库的基本使用,调用起来可能会不够灵活,可以通过读取配置文件的方式去配置日志
- 日志是为了方便调试和查错,在必要的函数内,都需要加上日志