python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等。
主要包括四部分:
1、loggers
loggers 就是程序可以直接调用的一个日志接口,可以直接向logger写入日志信息。logger并不是直接实例化使用的,而是通过logging.getLogger(name)来获取对象,事实上logger对象是单例模式,logging是多线程安全的,也就是无论程序中哪里需要打日志获取到的logger对象都是同一个。但是不幸的是logger并不支持多进程,这个在后面的章节再解释,并给出一些解决方案。
【注意】loggers对象是有父子关系的,当没有父logger对象时它的父对象是root,当拥有父对象时父子关系会被修正。举个例子,logging.getLogger(“abc.xyz”) 会创建两个logger对象,一个是abc父对象,一个是xyz子对象,同时abc没有父对象,所以它的父对象是root。但是实际上abc是一个占位对象(虚的日志对象),可以没有handler来处理日志。但是root不是占位对象,如果某一个日志对象打日志时,它的父对象会同时收到日志,所以有些使用者发现创建了一个logger对象时会打两遍日志,就是因为他创建的logger打了一遍日志,同时root对象也打了一遍日志。
2、Handlers
Handlers 将logger发过来的信息进行准确地分配,送往正确的地方。举个栗子,送往控制台或者文件或者both或者其他地方(进程管道之类的)。它决定了每个日志的行为,是之后需要配置的重点区域。
每个Handler同样有一个日志级别,一个logger可以拥有多个handler也就是说logger可以根据不同的日志级别将日志传递给不同的handler。当然也可以相同的级别传递给多个handlers这就根据需求来灵活的设置了。
3、Filters
Filters 提供了更细粒度的判断,来决定日志是否需要打印。原则上handler获得一个日志就必定会根据级别被统一处理,但是如果handler拥有一个Filter可以对日志进行额外的处理和判断。例如Filter能够对来自特定源的日志进行拦截or修改甚至修改其日志级别(修改后再进行级别判断)。
logger和handler都可以安装filter甚至可以安装多个filter串联起来。
4、Formatters
Formatters 指定了最终某条记录打印的格式布局。Formatter会将传递来的信息拼接成一条具体的字符串,默认情况下Format只会将信息%(message)s直接打印出来。Format中有一些自带的LogRecord属性可以使用,如下表格:
1、logger.py文件
import logging
import logging.handlers
import logging.config
import os
class InfoFilter(logging.Filter):
def filter(self, record):
if record.levelno == logging.INFO:
return super().filter(record)
else:
return 0
#定义日志输出地址根目录
log_dir = './logs'
#定义日志框架
log_dict = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s | %(process)d | %(levelname)s | %(filename)s | %(funcName)s | %(lineno)d | %(message)s'
}
},
'filters': {
'info_filter': {
'()': InfoFilter,
},
},
'handlers': {
'info': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(log_dir, 'info.log'),
'when': 'H',
'formatter': 'standard',
'filters': ['info_filter']
},
'error': {
'level': 'ERROR',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(log_dir, 'error.log'),
'when': 'H',
'formatter': 'standard'
},
},
'loggers': {
'info_logger': {
'handlers': ['info'],
'level': 'INFO'
},
'error_logger': {
'handlers': ['error'],
'level': 'ERROR'
},
},
}
#配置日志框架
logging.config.dictConfig(log_dict)
#创建logger对象,在调用getLogger时要提供Logger的名称
info_logger = logging.getLogger('info_logger')
error_logger = logging.getLogger('error_logger')
2、使用
from .logger import info_logger, error_logger
info_logger.info("需要输出的日志内容信息")
error_logger.error("需要输出的错误信息") #一般与try...except搭配使用
参考文献:
1、以打印日志为荣之logging模块详细使用