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

spawn/fork不同上下文下Python多进程日志记录异常排查

解决spawn模式下子进程日志队列无输出的问题

问题本质

spawn模式启动子进程时,会启动全新的Python解释器并重新导入主模块代码,主进程中已配置的Logger(包括QueueHandler)不会被子进程继承。这就是为什么子进程直接调用queue.put()能正常工作(队列是跨进程共享的),但用logger.error()无输出——子进程的Logger根本没关联到共享队列。

解决思路与实现

1. 子进程中重新配置Logger并关联共享队列

把共享队列作为参数传递给子进程,在子进程内部为Logger添加QueueHandler,确保日志能进入共享队列:

def worker(shared_queue):
    # 初始化子进程的Logger
    logger = logging.getLogger("worker_logger")
    logger.setLevel(logging.ERROR)
    
    # 清除默认handler(避免重复输出或无关输出)
    for handler in logger.handlers[:]:
        logger.removeHandler(handler)
    
    # 关联共享队列的QueueHandler
    queue_handler = QueueHandler(shared_queue)
    logger.addHandler(queue_handler)
    
    # 测试日志输出
    logger.error("子进程生成的错误日志")

2. 主进程日志配置必须放在if __name__ == '__main__':块内

spawn模式下子进程会重新执行主模块代码,所有不需要子进程执行的逻辑(比如队列创建、日志监听器启动、子进程启动)都要放在主入口块里,避免重复初始化:

if __name__ == '__main__':
    # 使用spawn上下文创建跨进程队列
    ctx = multiprocessing.get_context("spawn")
    log_queue = ctx.Queue()
    
    # 主进程配置日志监听器(负责从队列取日志并写入文件/控制台)
    file_handler = logging.FileHandler("unified.log")
    file_handler.setFormatter(logging.Formatter("%(asctime)s - %(processName)s - %(levelname)s - %(message)s"))
    listener = QueueListener(log_queue, file_handler)
    listener.start()
    
    # 启动守护子进程,传递共享队列
    daemon_process = ctx.Process(target=worker, args=(log_queue,))
    daemon_process.daemon = True
    daemon_process.start()
    
    # 主进程日志测试
    main_logger = logging.getLogger("main_logger")
    main_logger.addHandler(QueueHandler(log_queue))
    main_logger.error("主进程生成的错误日志")
    
    # 等待子进程执行完成(实际守护进程会一直运行,这里仅示例)
    daemon_process.join()
    listener.stop()

3. 验证子进程Logger配置(排障用)

如果还是没输出,可以在子进程中打印Logger的handler列表,确认是否正确关联了共享队列:

def worker(shared_queue):
    # ... 其他配置代码 ...
    print(f"子进程Logger的Handlers: {logger.handlers}")
    print(f"QueueHandler关联的队列: {logger.handlers[0].queue is shared_queue}")

4. 避免root Logger的全局配置冲突

尽量不要直接修改root Logger的配置,而是为不同模块/进程创建独立的Logger实例,避免子进程重新导入时root Logger的配置被重置或覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:35:24