You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Logging:如何销毁并重建Logger实例?

解决Python日志重复输出的问题

你的问题根源在于Python的logging模块中,同名Logger是单例模式——每次调用logging.getLogger(LOGGER_NAME)都会返回同一个Logger实例,而你每次调用__create_logger时,都会给这个实例添加新的FileHandler和StreamHandler。随着调用次数增加,Handler数量越来越多,每条日志就会被所有Handler各输出一次,导致重复。

要解决这个问题,你需要在创建新的Handler之前,先清空旧Logger上的所有Handler,同时关闭这些Handler以释放资源(比如文件句柄)。

修改后的代码实现

def __create_logger(log_level_console = logging.WARNING, log_level_file = logging.INFO, file_name = LOG_FILE_STANDARD):
    global LOGGER_NAME, LOG_IMMER
    global LOG_FORMAT_FILE_TIME, LOG_FORMAT_FILE_NACHRICHTEN
    global LOG_FORMAT_CONSOLE_TIME, LOG_FORMAT_CONSOLE_NACHRICHT
    
    # 获取目标Logger实例(单例)
    log = logging.getLogger(LOGGER_NAME)
    
    # 清理旧的Handler:遍历并移除所有已存在的Handler,同时关闭它们
    for handler in list(log.handlers):
        log.removeHandler(handler)
        handler.close()
    
    # 创建新的文件Handler
    logger_filename = file_name
    log_file_formatierer = logging.Formatter(LOG_FORMAT_FILE_NACHRICHTEN, LOG_FORMAT_FILE_TIME)
    log_file_handler = logging.FileHandler(logger_filename, mode = 'a')
    log_file_handler.setLevel(log_level_file)
    log_file_handler.setFormatter(log_file_formatierer)

    # 创建新的控制台Handler
    log_console_formatierer = logging.Formatter(LOG_FORMAT_CONSOLE_NACHRICHT, LOG_FORMAT_CONSOLE_TIME)
    log_console_handler = logging.StreamHandler()
    log_console_handler.setLevel(log_level_console)
    log_console_handler.setFormatter(log_console_formatierer)

    # 添加新Handler到Logger
    log.addHandler(log_console_handler)
    log.addHandler(log_file_handler)
    log.setLevel(logging.NOTSET)
    log.log(LOG_IMMER, 'logger angelegt, LogLevel (Konsole): {}, LogLevel (Datei): {}, Dateiname: {}'.format(log_level_console, log_level_file, file_name))
    return log

关键说明

  1. 清理旧Handler:通过list(log.handlers)遍历(用list避免遍历过程中修改原列表报错),逐个移除并关闭Handler,确保旧的文件流和控制台输出被彻底清理。
  2. 单例Logger的特性:你不需要“销毁”g_log变量——因为Logger实例由logging模块全局缓存,变量赋值只会改变引用,不会影响Logger本身。清理Handler才是解决重复输出的核心。
  3. 保持原逻辑:你的log.setLevel(logging.NOTSET)设置是合理的,它会让Logger传递所有日志消息给Handler,由Handler自身的log_level_console和log_level_file来过滤输出,符合你控制台固定WARNING、文件可配置级别的需求。

现在你再多次调用__create_logger切换日志文件时,就不会出现重复输出的问题了。

内容的提问来源于stack exchange,提问作者am2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:07:28