Python日志重复输出问题排查与解决方案
本文分析Python中使用logging模块时常见的日志重复打印问题。由于每次调用日志函数都会重新添加Handler,导致控制台和文件输出重复。文章提供了两种解决方案:一是使用单例模式预先实例化Logger对象;二是在添加Handler前判断handlers列表是否为空,从而避免重复注册。
日志重复输出问题现象
在使用Python的logging模块进行日志记录时,开发者经常遇到日志内容被重复输出的现象。
首先,我们查看log.py文件的具体实现代码:
问题复现代码分析
代码示例:
'''
功能描述:实现控制台和文件同时记录日志的功能
编写人:超哥
编写日期:
步骤分析:
1-配置日志记录器名称
2-配置日志级别
3-配置日志格式(可以分别设置,也可以统一设置)
4-创建并添加handler-控制台
5-创建并添加handler-文件
6-提供对外获取logger
'''
import logging
import sys
def log():
# 1 - 配置日志记录器名称
logger = logging.getLogger('AutoTest')
# 2-配置日志级别
logger.setLevel(logging.DEBUG)
# 3-配置日志格式(可以分别设置,也可以统一设置)
format = logging.Formatter('%(name)s-%(asctime)s-%(message)s')
# 4 - 创建并添加handler - 控制台
sh = logging.StreamHandler()
sh.setFormatter(format)
logger.addHandler(sh)
# 5 - 创建并添加handler - 文件
fh = logging.FileHandler('test.log')
fh.setFormatter(format)
logger.addHandler(fh)
# 6 - 提供对外获取logger
return logger
if __name__ == '__main__':
logger = log()
logger.info('使用函数定义的log方法')
接着,在同一目录下创建另一个测试文件:
在该文件中导入之前编写好的log.py模块。
from xx目录 import log
log().info('xxx1')
log().info('xxx2')
log().info('xxx3')
运行代码后的输出结果如下:

这种重复输出并非预期行为,而是使用logging模块时常见的陷阱。通过调试观察可以发现,每次调用日志记录函数时,都会重新创建并添加Handler,从而导致日志重复打印。
第一次调用后,logger对象的handlers属性中已经包含两个Handler实例:一个是控制台输出的StreamHandler,另一个是文件输出的FileHandler。

随后的调用会再次尝试添加Handler,导致handlers列表中增加新的StreamHandler实例。

解决方案一:单例模式
为了解决这一问题,这里提供两种可行的解决方案,并分别列出对应的代码实现。
第一种方案是采用单例模式。在log.py文件中增加一行代码:logger = log()。这行代码的作用是在模块加载时提前实例化Logger对象。其他模块在导入时应改为:from xxx包.log import logger,随后直接使用logger.info('xxxx')输出日志即可。
……省略上方代码
# 6 - 提供对外获取logg的方法
return logger
#增加一行
logger = log()
if __name__ == '__main__':
logger = log()
logger.info('使用函数定义的log方法')
导入方式调整为:
from xx包 import logger
logger.info('xxx1')
logger.info('xxx2')
logger.info('xxx3')
此时的输出结果符合预期,不再重复。

解决方案二:条件添加Handler
第二种方案是在log.py中每次添加Handler前,判断handlers列表是否已存在内容。
……
# 4 - 创建并添加handler - 控制台
sh = logging.StreamHandler()
sh.setFormatter(format)
# 5 - 创建并添加handler - 文件
fh = logging.FileHandler('test.log')
fh.setFormatter(format)
#在新增handler时判断是否为空
if not logger.handlers:
logger.addHandler(sh)
logger.addHandler(fh)
# 6 - 提供对外获取logg的方法
return logger
if __name__ == '__main__':
logger = log()
logger.info('使用函数定义的log方法')
导入文件的代码保持原样不变:
from xx包 import log
log().info('xxx1')
log().info('xxx2')
log().info('xxx3')
运行后的输出结果正常,无重复现象。

对于面向对象封装的日志方案,同样适用上述两种解决思路,读者可自行调整代码实现。
总结
本文介绍了Python控制台打印log输出重复的原因及解决方法,更多相关python打印log重复内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









