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

Python多进程超时错误时仅杀子进程留父进程的内存溢出问题

问题原因分析

你的内存泄漏问题来自三个核心疏漏:

  • 只有my_func正常执行完成的分支调用了pool.close(),超时异常分支没有对Pool对象做任何资源清理,每次超时都会泄漏Pool内部的进程引用、队列、缓存等资源,是内存持续上涨的核心原因
  • 正常分支仅调用了pool.close(),没有配套调用pool.join()等待子进程完全退出,资源回收不完全
  • kill_proc_tree只调用了child.kill(),没有等待子进程退出回收状态,会产生僵尸进程,额外占用系统资源
修复方案

建议优先用multiprocessing标准库自带的能力做进程清理,比自定义的进程树查杀更稳定可靠,修复后代码如下:

import os
import multiprocessing as mp
import traceback
import psutil

# 父进程PID全局只需要获取一次,运行期间不会变化
parent_pid = os.getpid()

def kill_proc_tree(pid):
    parent = psutil.Process(pid)
    children = parent.children(recursive=True)
    for child in children:
        child.kill()
    # 新增等待子进程退出,回收状态
    for child in children:
        child.wait(timeout=3)

while True:
    pool = None
    try:
        pool = mp.Pool(processes=1, maxtasksperchild=1)
        result = pool.apply_async(my_func, args=())
        result.get(timeout=60)
    except mp.context.TimeoutError:
        traceback.print_exc()
        kill_proc_tree(parent_pid)
    except Exception:
        # 覆盖其他所有异常场景,避免漏处理
        traceback.print_exc()
    finally:
        # 所有分支统一走finally做资源清理,保证资源一定释放
        if pool is not None:
            pool.terminate()
            pool.join()
            pool.close()
关键修改说明
  • 新增finally块统一做Pool资源清理,无论正常执行还是抛出任何异常,都会终止Pool的工作进程、等待进程退出、释放Pool占用的所有内存资源
  • 在kill_proc_tree中新增child.wait()调用,主动回收被杀死的子进程状态,避免产生僵尸进程
  • 新增通用异常捕获分支,避免其他非超时异常导致资源泄漏
  • 取消重复获取父进程PID的冗余逻辑,父进程运行期间PID不会变化

如果你不需要额外查杀my_func启动的第三方子进程,完全可以删掉自定义的kill_proc_tree函数,仅靠pool.terminate() + pool.join()就能完全清理Pool启动的工作进程,资源回收效率更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:48:01