如何解决Python Logger日志重复输出的问题
解决Python自定义Logger日志重复输出问题
问题描述
我编写了一个带有不同级别格式化器的自定义Python Logger,输出的.txt文件格式正确,但每条日志语句都会重复。
原代码
import os import sys import time import datetime import logging # 切换工作目录 os.chdir('C:\Git_Repo\pyautotest\AutoTest\OutputLogs') def timeStamped(fname, fmt='%Y-%m-%d_%H.%M.%S - {fname}'): return datetime.datetime.now().strftime(fmt).format(fname=fname) # 日志级别说明 # DEBUG: 详细诊断信息,仅排查问题时有用 # INFO: 确认系统正常运行 # WARNING: 出现意外情况或潜在问题,但系统仍可正常工作 # ERROR: 系统无法执行某些功能,问题较严重 # CRITICAL: 严重错误,程序可能无法继续运行 PrintLog = logging.getLogger(__name__) PrintLog.setLevel(logging.DEBUG) class MyFormatter(logging.Formatter): debug_fmt = "%(levelname)s: %(asctime)s: %(pathname)s: Line %(lineno)s: %(message)s" info_fmt = "%(levelname)s: %(asctime)s: %(message)s" error_fmt = "%(levelname)s: %(asctime)s: %(pathname)s: Line %(lineno)s: ERROR - %(message)s" def __init__(self): super().__init__(fmt="%(levelno)d: %(msg)s", datefmt='%Y-%m-%d_%H.%M', style='%') def format(self, record): # 保存原始格式 format_orig = self._style._fmt # 根据日志级别切换格式 if record.levelno == logging.DEBUG: self._style._fmt = MyFormatter.debug_fmt elif record.levelno == logging.INFO: self._style._fmt = MyFormatter.info_fmt elif record.levelno == logging.ERROR: self._style._fmt = MyFormatter.error_fmt # 执行格式化 result = logging.Formatter.format(self, record) # 恢复原始格式 self._style._fmt = format_orig return result fmt = MyFormatter() PrintLog.propagate = False stream = logging.Formatter('%(message)s') stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.DEBUG) stream_handler.setFormatter(stream) debug_handler = logging.FileHandler(timeStamped('Test Log.txt')) debug_handler.setFormatter(fmt) info_handler = logging.FileHandler(timeStamped('Test Log.txt')) info_handler.setFormatter(fmt) PrintLog.addHandler(debug_handler) PrintLog.addHandler(info_handler) PrintLog.addHandler(stream_handler)
日志输出示例
INFO: 2023-11-20_11.07: Comencing Autotest. INFO: 2023-11-20_11.07: Comencing Autotest. INFO: 2023-11-20_11.07: Operating System = Windows INFO: 2023-11-20_11.07: Operating System = Windows DEBUG: 2023-11-20_11.07: C:\Git_Repo\pyautotest\AutoTest\Chris PyAuto Dev\new_test_menu.py: Line 48: Quitting DEBUG: 2023-11-20_11.07: C:\Git_Repo\pyautotest\AutoTest\Chris PyAuto Dev\new_test_menu.py: Line 48: Quitting
解决方案
问题根源
你给同一个日志器添加了两个功能完全重复的FileHandler(debug_handler和info_handler),它们指向同一个日志文件、使用相同的格式化器。无论日志级别是INFO还是DEBUG,两个handler都会处理并写入文件,导致每条日志被输出两次。
修复方案
只保留一个FileHandler即可——你的自定义MyFormatter已经能根据日志级别自动切换输出格式,不需要为不同级别单独创建handler。
修改后的代码
import os import sys import time import datetime import logging # 切换工作目录 os.chdir('C:\Git_Repo\pyautotest\AutoTest\OutputLogs') def timeStamped(fname, fmt='%Y-%m-%d_%H.%M.%S - {fname}'): return datetime.datetime.now().strftime(fmt).format(fname=fname) # 日志级别说明(可保留原注释内容) PrintLog = logging.getLogger(__name__) PrintLog.setLevel(logging.DEBUG) class MyFormatter(logging.Formatter): debug_fmt = "%(levelname)s: %(asctime)s: %(pathname)s: Line %(lineno)s: %(message)s" info_fmt = "%(levelname)s: %(asctime)s: %(message)s" error_fmt = "%(levelname)s: %(asctime)s: %(pathname)s: Line %(lineno)s: ERROR - %(message)s" def __init__(self): super().__init__(fmt="%(levelno)d: %(msg)s", datefmt='%Y-%m-%d_%H.%M', style='%') def format(self, record): format_orig = self._style._fmt if record.levelno == logging.DEBUG: self._style._fmt = MyFormatter.debug_fmt elif record.levelno == logging.INFO: self._style._fmt = MyFormatter.info_fmt elif record.levelno == logging.ERROR: self._style._fmt = MyFormatter.error_fmt result = logging.Formatter.format(self, record) self._style._fmt = format_orig return result fmt = MyFormatter() PrintLog.propagate = False stream = logging.Formatter('%(message)s') stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.DEBUG) stream_handler.setFormatter(stream) # 仅保留一个FileHandler file_handler = logging.FileHandler(timeStamped('Test Log.txt')) file_handler.setFormatter(fmt) PrintLog.addHandler(file_handler) PrintLog.addHandler(stream_handler)
效果验证
修改后,每条日志只会被写入一次,同时依然保留不同级别对应的格式化效果。
内容的提问来源于stack exchange,提问作者Chris Trace
相关产品推荐
相关产品推荐

