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

如何在回调中重置Python Logger?线程日志重复写入问题

问题分析与解决方案

问题原因

logging.basicConfig() 是全局日志配置的快捷方法,仅会在第一次调用时生效——它会初始化根日志器的输出文件、级别和格式,后续所有调用都会被直接忽略。

你的代码中每个线程都调用basicConfig,但只有第一个线程的配置会生效,后续线程的filename参数不会被处理。同时,你创建的各个线程专属Logger默认会将日志传播给根日志器,所以所有最终日志都会写入第一个线程创建的文件中,和你给Logger命名无关。

修复方案

放弃使用logging.basicConfig,手动为每个线程的Logger创建独立的FileHandler,确保每个Logger对应单独的日志文件:

def do_work(self, conn, ch, delivery_tag, body):
    thread_id = threading.get_ident()
    log_filename = f"{self.dict_config['filelog']}exchange_hashed_{thread_id}_{datetime.now().strftime('%Y%m%d%H%M%S%f')}.log"
    
    # 创建线程专属Logger
    logger = logging.getLogger(f'exchange_hashed{thread_id}')
    logger.setLevel(logging.INFO)
    # 关闭日志传播,避免日志同时写入根日志器(可选,根据需求调整)
    logger.propagate = False
    
    # 检查是否已添加Handler,防止重复添加(比如Logger被意外复用的情况)
    if not logger.handlers:
        # 创建文件输出Handler
        file_handler = logging.FileHandler(log_filename)
        # 设置日志格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        file_handler.setFormatter(formatter)
        # 将Handler绑定到当前Logger
        logger.addHandler(file_handler)
    
    # 后续日志逻辑保持不变
    logger.info('Thread id: %s Delivery tag: %s', thread_id, delivery_tag)
    payload = body.decode("utf-8")
    payload = json.loads(payload)
    file_content = payload["values"]
    file_path = file_content["header"]["meta_data"]["file_name"]
    filename = file_path.split("/")[-1]
    logger.info(f"Data received for {filename}")

关键说明

  • 每个线程的Logger通过thread_id保证命名唯一,不会重复获取同一个Logger实例
  • 手动创建的FileHandler直接绑定到当前Logger,确保日志输出到指定文件
  • logger.propagate = False 可以避免日志同时被根日志器处理(如果根日志器有其他输出的话,可选添加)
  • 检查logger.handlers是否为空,是为了防止Logger被意外复用(比如线程ID重复的极端情况)时重复添加Handler,导致日志重复输出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:15:26