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
相关产品推荐
相关产品推荐

