Python多进程:如何在异常情况下关闭多进程池

10

我正在使用Python的多进程模块来将长时间的进程拆分并行运行。除了当一个子进程出现异常时,进程池没有关闭且在服务器上仍可以看到这些进程外,它都能正常工作。

以下是代码:

from multiprocessing import Pool
pool = Pool(processes=4)
from functools import partial
param_data = "Test Value"
func = partial(test_function, param_data)
r = pool.map(func, range(3))
pool.close()

def test_function(param_data,index):
   try:
      # The process here;
   except Exception as e:
      # Close the process pool;
在except块中使用pool.close时,报错:

NameError: global name 'pool' is not defined

我尝试使用以下代码在发生异常时关闭进程。

    except Exception as e:
       import os
       import signal
       pid = os.getpid()
       os.kill(pid, signal.SIGTERM) 
但是我仍然可以在服务器上看到进程。这仍然不是最好的解决方案,因为这只会终止遇到异常的子进程,而其他进程仍将继续。

我希望所有进程在完成时都能终止,无论它们是否遇到异常。

我正在运行Python2.7

附言:我不能在服务器上安装像psutil这样的新库,我正在寻找使用标准python库的解决方案。

我查看了一些类似的问题,例如在此论坛中自动终止进程和子进程,但它们并没有真正解决这个问题。


1
在调用 pool.close() 之前,你尝试使用 r.get() 获取结果了吗?我认为在调用 pool.map() 后获取结果后,进程才会退出。哦,还有,你不应该尝试从子进程中访问 pool 对象,因为文档说:请注意,池的方法只能由创建它的进程使用。 - Maciek
谢谢@Maciek,我通过将整个父进程代码放在try ... except块中得到了解决方案。我已经在下面分享了答案。 - Codeformer
2个回答

7
我有解决方案 - 在父进程中捕获异常。
try:
   pool = Pool(processes=4)
   from functools import partial
   param_data = "Test Value"
   func = partial(test_function, param_data)
   r = pool.map(func, range(3))
except Exception as e:
   pool.close()
pool.close()

在子进程函数中添加try/catch语句:

def test_function(param_data,index):
    try:
       # The process here;
    except Exception as e:
       raise Exception(e.message)          

这里的except块看起来多余,但实际上并不是。原因是,子进程引发的某些异常未被传递到父进程。
例如,我在函数中引发了一个自定义异常,但它未被传递到父进程。因此建议在子进程内捕获所有异常并从那里引发标准异常,然后在父进程中处理它,在那里可以关闭进程池或进行其他清理操作。

我认为 pool.close() 不足以释放所有资源。在此之后,您应该调用 pool.terminate() - decadenza

1
你需要使用以下代码:
在Pool.terminate和Pool.join之后添加del Pool
这将解决你的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接