问题
在最近的工作当中,需要使用到python的一个常见库叫做logging,这个库可以用于项目的日志记录,但是在我使用的过程当中却需要多个log对象分别输出到不同的日志文件当中的时候,我使用以下代码失败了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='test.log', filemode='w')
log = logging log.debug('debug message')
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='test2.log', filemode='w')
log = logging log.debug('debug message')
|
按照我浅薄的理解,这应该是两个对象才对,但是为啥最后只有一个日志文件生成,第二个对象并没有生成日志文件呢?
原因
根据官方的解释:
根据basicConfig源码可以发现只有当“handlers”的长度为0时才会进行日志信息配置,否则跳过该配置步骤。那么在步骤1中root已经自动进行了日志信息配置,“handlers”的长度不为0,则步骤2中的“logging.basicConfig”并没有达到日志信息配置的作用。
那么有没有什么办法可以解决呢?
解决没办法配置的问题的答案当然是有的,那就是在python3.8及之后在basicConfig中新增了force参数,当“force=True”时可以强制进行日志信息重新设置。也就是如下代码:
1 2 3 4 5 6
| logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='test.log', filemode='w', force=True)
|
但是这还是有问题,因为这个仅仅支持重新配置,并不支持将对象保存起来因此如果代码写成了下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='test.log', filemode='w', force=True)
log1 = logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='test2.log', force=True, filemode='w')
log2 = logging log1.debug('debug message') log2.debug('debug message')
|
运行之后就会发现,虽然是两个对象,也生成了两个日志文件,但是却只能往一个文件里面输入日志信息,也就是最后指定的那个文件。
后续疑问
假设就是需要同时存在两个不同的log对象,用于写入不同的日志文件该怎么办?如果是上述方法,也不可能需要写的时候立马修改吧。在学习中我发现另一种方法能够解决这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| NG_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': "[%(levelname)s][%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]" "[%(message)s]" }, 'simple': { 'format': "[%(levelname)s] [%(asctime)s] [%(name)s] [%(filename)s:%(lineno)d] [%(message)s]" }, }, 'filters': {}, 'handlers': { 'file': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', 'filename': "log.log", 'maxBytes': 15 * 1024 * 1024, 'backupCount': 10, 'formatter': 'simple' }, 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple' }, }, 'loggers': { 'tasks': { 'handlers': ["file"], 'level': 'INFO', 'propagate': False, }, '': { 'handlers': ["file"], 'level': 'INFO', 'propagate': False, } } }
logging.config.dictConfig(LOGGING_DIC) logger1 = logging.getLogger('tasks') logging.info("123123123")
|
使用字典配置的方法可以解决需要创建多个log对象的问题。