Python logging模块学习
logging模块日志记录工具
摘自Python文档
日志是对软件执行时所发生事件的一种追踪方式。软件开发人员对他们的代码添加日志调用,借此来指示某事件的发生。一个事件通过一些包含变量数据的描述信息来描述(比如:每个事件发生时的数据都是不同的)。开发者还会区分事件的重要性,重要性也被称为 等级 或 严重性
基础教程
日志级别
级别 | 何时使用 |
---|---|
DEBUG | 细节信息,仅当诊断问题时适用。 |
INFO | 确认程序按预期运行 |
WARNING | 表明有已经或即将发生的意外,程序仍按预期进行 |
ERROR | 由于严重的问题,程序的某些功能已经不能正常执行 |
CRITICAL | 严重的错误,表明程序已不能继续执行 |
默认的级别是
WARNING
基础用法
import logging
# 基础日志教程
# logging.xxx(msg: Any)
logging.debug("debug:这是一个debug提醒")
logging.info("info:这是一个info提醒")
logging.warning("warning:这是一个warning提醒")
logging.error("error:这是一个error提醒")
logging.critical("critical:这是一个critical提醒")
# 输出:WARNING:root:warning:这是一个warning提醒
# 输出:ERROR:root:error:这是一个error提醒
# 输出:CRITICAL:root:critical:这是一个critical提醒
因为默认的级别是 WARNING 所以以上只有比WARNING级别高的会输出
以上输出只能输出到控制台,而一般情况下都是将日志输出到日志文件中去:
import logging
# 输出到日志文件中
# logging.basicConfig()参数
# filename="日志文件完整路径",filemode="日志输出的方式:a追加,w覆盖 默认是追加"
# format="日志输出的格式" datefmt="输出日期的格式",level=logging.日志输出级别
logging.basicConfig(filename="log_1.log", level=logging.DEBUG, filemode="w",
format="%(asctime)s>%(levelname)s>%(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logging.debug("输入到log_1.log:这是一个debug提醒")
logging.info("输入到log_1.log:这是一个info提醒")
basicConfig()指定了filename就不会在控制台输出了,打开log_1.log文件可以看到如下 输出:
2021-12-11 17:03:10>DEBUG>输入到log_1.log:这是一个debug提醒
2021-12-11 17:03:10>INFO>输入到log_1.log:这是一个info提醒
日志记录的格式依次是:asctime 日期格式,levelname 日志等级,message 日志内容;
提示: basicConfig() 的调用应该在 debug() , info() 等的前面。因为它被设计为一次性的配置,只有第一次调用会进行操作,随后的调用不会产生有效操作
进阶教程
大致流程:获取记录器Logger>过滤器Filter>给记录器添加处理程序Handler>设置处理程序Handler的格式化程序Formatter>记录器Logger发送不同级别的消息;
记录器Logger
首先通过logging.getLogger(name)来获取记录器,然后为记录器设置日志等级:
# 获取记录器
logger = logging.getLogger(__name__)
# 设置记录器级别
logger.setLevel(logging.DEBUG)
过滤器Filter
过滤器Filter 可以添加到记录器Logger 和 处理程序Handler
Filter提供更加细粒度的过滤,甚至可以改变消息记录LogRecord的属性:包括 msg levelno等
所有逻辑性的操作在filter(record)这个方法里面;该方法根据条件判断返回False则过滤掉,返回True则保留。
可以借鉴对高阶函数filter的理解,如果return False则删除,return True则保留
过滤器 Filter 可以通过以下三种方法实现:
方法一:定义一个类,类中包含filter(record)方法:
class Filter_Class(object):
"""方法一:定义一个filter类,具有filter方法"""
def __init__(self, arg1="测试", arg2=":改变日志消息记录message"):
self.arg1 = arg1
self.arg2 = arg2
def filter(self, record):
# 改变日志消息记录的msg属性:msg 后添加上 self.arg2
record.msg = record.msg + self.arg2
if record.msg.startswith(self.arg1) is True:
# 如果 日志消息是以"测试"开头,则不要输出
return False
return True
利用该类的实例,添加过滤器Filter到记录器或者处理程序:
# 创建 过滤器 filter
# 利用方法一Filter_Class类的实例:
filter = Filter_Class()
# addFilter方法 给记录器添加过滤器
logger.addFilter(filter)
# :因为filter的存在,该条日志消息将不会打印
logger.info("测试:因为filter的存在,该条日志消息将不会打印")
方法二:定义一个filter函数 :
def filter_func(record, arg1="测试", arg2=":改变日志消息记录message"):
"""方法二:定义一个filter函数"""
record.msg = record.msg + arg2
if record.msg.startswith(arg1) is True:
# 如果 日志消息是以"测试"开头,则不要输出
return False
return True
通过 logging.Filter对象添加过滤器Filter到记录器或者处理程序:
# 利用方法二:通过 logging.Filter对象 filter
filter = logging.Filter()
filter.filter = filter_func
# addFilter方法 给记录器添加过滤器
logger.addFilter(filter)
# :因为filter的存在,该条日志消息将不会打印
logger.info("测试:因为filter的存在,该条日志消息将不会打印")
方法三 :和方法二 一样;通过lambda匿名函数给logging.Filter对象filter传递filter函数:
filter = logging.Filter()
# lambda函数逻辑:如果日志消息是以"测试"开头则返回False 否则返回True
filter.filter = lambda record