python之logging模块的简单使用
一、配置日志信息(调用时只有效一次,后面再调用时就无效)(日志输出的位置,输出的日志级别,日志显示的格式,日志的日期);不配置日志信息,默认不会在控制台输出且默认输出日志级别是warning及以上的日志
注:此配置是对根记录器的handler进行配置。子记录器没有配置handler时,日志输出格式按根记录器的日志格式进行输出;如果子记录器也配置了handler,则日志输出时,会打印两遍,一遍是子记录器的日志格式,一遍是根记录器的日志格式,因为子记录器的propagate属性默认为True,会将子记录器的日志消息传递到父级记录器的处理程序中,所以会输出两遍日志。解决此类问题有两种,一是避免设置根记录器的handler,而是为每个子记录器logger配置handler,第二步的代码做了修改,仅供参考;二是将记录器的propagate属性设置为False,禁止将日志消息传递给父级记录器的处理程序,推荐使用
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, format="%(asctime)s %(name)s %(levelname)s %(message)s", datefmt='%Y-%m-%d %H:%M:%S %a')
二、这里自定义了一个装饰器,用于为每一个函数或方法提供单独的logger实例。ps:为类方法提供共享的日志记录器(classname.logger)参考以下写法
def func_logging(func_name): """
将日志记录器实例logger添加到函数作用域中,每个函数都有自己的日志记录器
函数装饰器,向函数的作用域中加入logger实例,
便于每个函数都可以有自己的日志记录器
:param func_name: 函数对象-function object
:return: 函数对象-function object
"""
func_name.__dict__['logger'] = logging.getLogger(__file__ + ' ' + func_name.__qualname__)
# 获取logger实例
logger = func_name.__dict__["logger"]
# 设置logger实例的日志级别:输出到指定位置的最低日志级别是debug,高于此级别的日志也将被输出
logger.setLevel(logging.DEBUG)
# 创建一个处理程序,用于向控制台输出日志信息
handler1 = logging.StreamHandler(stream=sys.stderr)
file_handler = logging.FileHandler(filename="./info.log", encoding="utf-8", mode="w")
# 设置处理程序处理的日志级别:处理程序要处理的最低日志级别,高级此级别的日志也会被处理程序进行处理
handler1.setLevel(logging.DEBUG)
file_handler.setLevel(logging.DEBUG)
# 创建一个Formatter实例,用于格式化日志样式
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
# 将自定义的日志样式添加到处理程序
handler1.setFormatter(formatter)
file_handler.setFormatter(formatter)
# 向logger记录器添加处理程序
logger.addHandler(handler1)
logger.addHandler(file_handler)
# 两个handler,一个输出到控制台,一个输出到磁盘文件
# print(logger.handlers)
# 一招解决子记录器的日志消息传递给父级记录器的处理程序输出两遍日志的问题
logger.propagate = False
return func_name
三、在函数中提取logger实例
# 在函数内,获取函数运行时的函数名字
current_function_name = sys._getframe().f_code.co_name logger_object = globals()[current_function_name]
# 提取logger实例
# 此logger是根日志记录器的子级,若logger没有配置handler,则使用父级的handler来处理日志消息。handler的作用是将日志消息输出到指定的位置
# 创建handler时,建议不要用Handler()类来实例化handler,该类是基类,提供了处理程序的接口,应使用其子类来进行实例化 logger = logger_object.__dict__.get('logger', None)
print(logger.handlers) # 返回一个空列表,没有handler
print(logger.hasHandlers()) # 返回True,证明子日志记录器有handler
print(logger.parent.handlers) # 返回父级的handler:[<StreamHandler <stderr> (NOTSET)>]
四、开始编写自己的日志信息
logger.debug()
logger.info()
logger.warning()
logger.error()
logger.critical()
浙公网安备 33010602011771号