由于不少小伙伴在使用logging.basicConfig基本日志配置时经常遇到乱码问题,这其实是因为basicConfig作为logging基本配置功能是并不支持修改编码方式的,想要解决该问题只能修改源码,但是这种方式我们是非常不提倡的,而且有很多功能是基本配置模块不能实现的,因此本篇文章将会介绍一种全新的配置方法-----日志配置字典
我们可以将logging模块所需要的各种配置都写在配置字典中,然后我们通过调用该字典让logging模块来使用这里的配置项
该字典模版不需要自己写,在需要使用的时候直接复制过去,你只要知道里面的各个功能该怎么使 用即可
# 日志配置字典
LOGGING_DIC = {
'version': 1.0,
'disable_existing_loggers': False,
# 日志格式
'formatters': {
'standard': {
'format': '%(asctime)s %(threadName)s:%(thread)d [%(name)s] %(levelname)s [%(pathname)s:%(lineno)d] %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'simple': {
'format': '%(asctime)s [%(name)s] %(levelname)s %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'test': {
'format': '%(asctime)s %(message)s',
}
},
'filters': {},
# 日志处理器
'handlers': {
'console_debug_handler': {
'level': 'DEBUG', # 日志处理的级别限制
'class': 'logging.StreamHandler', # 输出到终端
'formatter': 'simple' # 日志格式
},
'file_info_handler': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
'filename': 'abc.log',
'maxBytes': 1024 * 1024 * 10, # 日志大小 10M
'backupCount': 1000, # 日志文件保存数量限制
'encoding': 'utf-8',
'formatter': 'standard',
},
'file_debug_handler': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'filename': 'test.log', # 日志存放的路径
'encoding': 'utf-8', # 日志文件的编码
'formatter': 'test',
},
},
# 日志记录器
'loggers': {
'logger1': { # 导入时logging.getLogger时使用的app_name
'handlers': ['console_debug_handler'], # 日志分配到哪个handlers中
'level': 'DEBUG', # 日志记录的级别限制
'propagate': False, # 默认为True,向上(更高级别的logger)传递,设置为False即可,否则会一份日志向上层层传递
},
'logger2': {
'handlers': ['console_debug_handler', 'file_debug_handler'],
'level': 'INFO',
'propagate': False,
},
'': {
'handlers': ['console_debug_handler', 'file_info_handler'],
'level': 'INFO',
'propagate': False,
},
}
}
指定日志版本号,根据自身实际情况修改即可,一般不用管
'version': 1.0
是否禁用现有的日志记录器,默认False
'disable_existing_loggers': False,
formatters
日志格式,下面分了三种格式,格式名自己取就可以
'formatters': {
'standard': {...}
'simple': {...}
'test': {...}
}
standard
标准格式,format
即输出内容的格式,可以自行修改
datefmt
日期格式,也可以自行修改
'standard': {
'format': '%(asctime)s %(threadName)s:%(thread)d [%(name)s] %(levelname)s [%(pathname)s:%(lineno)d] %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
simple
和test
相比于standard
就是相对简洁一点,当然这三种格式都可以根据自己实际需求自行修改
'simple': {
'format': '%(asctime)s [%(name)s] %(levelname)s %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'test': {
'format': '%(asctime)s %(message)s',
},
filters
是过滤器,模版中并没有定义实际参数,如果有需求可以根据以下示例修改:
'()'
: 表示指定使用的过滤器类。在这个例子中,过滤器类是 my_module.MyFilter
。'parameter'
: 是过滤器的参数,可以根据实际需求进行设置。在这个例子中,参数值被设置为 'value'
'filters': {
'myfilter': {
'()': 'my_module.MyFilter',
'parameter': 'value'
}
},
handlers
和loggers
配合使用,handlers
是日志处理器,loggers
日志记录器负责生产不同级别的日志,然后将日志传给handlers
进行处理
'handlers': {...}
'loggers': {...}
日志是输出到控制台,亦或是写入的a文件还是b文件这都是由handlers
决定的,我们也可以设置不同的handler
做不同的处理,如下:
'handlers': {
'console_debug_handler': {...},
'file_info_handler': {...},
'file_debug_handler': {...},
'file_deal_handler': {...},
'file_operate_handler': {...}
},
console_debug_handler
见名知意,输出到控制台(console)的debug级别的日志处理器
'console_debug_handler': {
'level': 'DEBUG', # 日志处理的级别限制,10同理
'class': 'logging.StreamHandler', # 输出到终端
'formatter': 'simple' # 日志格式
},
file_info_handler
见名知意,写入文件的info级别的日志处理器
'file_info_handler': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
'filename': 'log.log', # 日志存放路径
'maxBytes': 800, # 日志大小 10M
'backupCount': 3, # 日志文件保存数量限制
'encoding': 'utf-8', # 日志文件编码
'formatter': 'standard', # 日志格式
'file_debug_handler': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'filename': 'test.log', # 日志存放路径
'encoding': 'utf-8', # 日志文件编码
'formatter': 'test', # 日志格式
},
刚刚的handlers
仅仅是负责处理日志,真正产生日志的是loggers
,比如logger1中handlers参数就是指定将日志交给哪个处理器处理
level
中的日志级别和handlers
中并不冲突,因为前者限制的是产生的日志,而后者则会再次根据自己的限制进行过滤
'loggers': {
'logger1': { # 导入时logging.getLogger时使用的app_name
'handlers': ['console_debug_handler'], # 日志分配到哪个handlers中
'level': 'DEBUG', # 日志记录的级别限制
'propagate': False, # 默认为True,向上(更高级别的logger)传递,设置为False即可,否则会一份日志向上层层传递
},
handlers
,这样就可以即输出到终端,也写入到日志'logger2': {
'handlers': ['console_debug_handler', 'file_debug_handler'],
'level': 'INFO',
'propagate': False,
},
import logging
需要注意的是logging本身是一个包,而logging下面有一个子包叫作config,而我们不能直接logging.config
这样会报错
正确的导入方式是:
import logging.config
接下来我们就可以使用logging模块了,首先将配置字典载入模块中
# 使用配置字典
logging.config.dictConfig(LOGGING_DIC) # 自动加载字典中的配置
获取日志记录器
log1 = logging.getLogger('logger1')
接下来就可以对日志进行各种操作了
import logging.config
logging.config.dictConfig(LOGGING_DIC)
log1 = logging.getLogger('logger1')
info = "张三今天取款1000元"
log1.debug(info)
当你想要调用同一个handlers
并且需要实现的功能相同时,为了避免代码冗余,只需要创建一个无名的loggers
即可
例如:
'': {
'handlers': ['console_debug_handler', 'file_info_handler'],
'level': 'INFO',
'propagate': False,
},
这个loggers
并没有命名,你可以在调用getLogger
时使用任意名称,当logging模块在检索字典时没有找到其对应的loggers
时会自动调用无名loggers
并且命名为你所输入的参数
比如我想创建一个’用户取款’的loggers
,但是可以看到我的字典中并没有该模块,而此时我依然可以执行程序
并且自动调用无名loggers
由于谁也不知道记录的日志会在什么时候突然有用,因此我们为了在不删除日志的前提下避免占用过多内存,引入新的概念-----日志轮转
'file_info_handler': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
'filename': 'info_level.log',
'maxBytes': 1024 * 1024 * 10, # 日志大小 10M
'backupCount': 1000, # 日志文件保存数量限制
'encoding': 'utf-8',
'formatter': 'standard',
},
日志轮转模块的意思就是当info_level.log
文件大小超过10MB时自动将其改名为info_level1.log
、info_level2.log
…
当创建的文件数量超过backupCount
设定的值时就会自动删除之前的文件
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
'maxBytes': 1024 * 1024 * 10, # 日志大小 10M
'backupCount': 1000, # 日志文件保存数量限制
雷区
tter’: ‘standard’,
},
- 日志轮转模块的意思就是当`info_level.log`文件大小超过10MB时自动将其改名为`info_level1.log`、`info_level2.log`...
- 当创建的文件数量超过`backupCount`设定的值时就会自动删除之前的文件
```python
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
'maxBytes': 1024 * 1024 * 10, # 日志大小 10M
'backupCount': 1000, # 日志文件保存数量限制
雷区
设置日志轮转的文件千万不要和其他handlers
创建的文件重名,否则会报错