为什么赢了';Python多处理工人会死吗?

为什么赢了';Python多处理工人会死吗?,python,python-multiprocessing,pypy,Python,Python Multiprocessing,Pypy,我正在使用python的多处理功能将一些函数映射到一些元素上。大致如下: def computeStuff(arguments, globalData, concurrent=True): pool = multiprocessing.Pool(initializer=initWorker, initargs=(globalData,)) results = pool.map(workerFunction, list(enumerate(arguments))) retu

我正在使用python的多处理功能将一些函数映射到一些元素上。大致如下:

def computeStuff(arguments, globalData, concurrent=True):
    pool = multiprocessing.Pool(initializer=initWorker, initargs=(globalData,))
    results = pool.map(workerFunction, list(enumerate(arguments)))
    return results

def initWorker(globalData):
    workerFunction.globalData = globalData

def workerFunction((index, argument)):
    ... # computation here
通常,我使用cPython和Pypy在ipython中运行测试。我注意到,生成的进程通常不会被杀死,因此它们开始累积,每个进程都使用一gig的ram。当在计算过程中按ctrl-k键时会发生这种情况,这会使多处理陷入混乱的狂乱之中。但即使让计算完成,这些进程也不会在Pypy中消亡

根据文档,当池被垃圾回收时,它应该调用
terminate()
并杀死所有进程。这里发生了什么事?是否必须显式调用
close()
?如果是,是否有某种上下文管理器可以正确管理关闭资源(即流程)


这是在Mac OS X Yosemite上的。

PyPy的垃圾收集很慢,因此未能调用
close
意味着
池将在“某个时候”清理,但这可能并不意味着“很快”

一旦
正确地
关闭
d,工作人员在完成任务时退出。在3.3 Python之前的版本中,确保关闭
池的一个简单方法是:

from contextlib import closing

def computeStuff(arguments, globalData, concurrent=True):
    with closing(multiprocessing.Pool(initializer=initWorker, initargs=(globalData,))) as pool:
        return pool.map(workerFunction, enumerate(arguments))
注意:我还删除了对
列表
的显式转换(毫无意义,因为
映射
将为您迭代
枚举
迭代器),并直接返回结果(无需指定名称,只需在下一行返回)

如果要确保在异常情况下(在3.3 Python之前版本)立即终止,可以使用try/finally块,或者编写一个简单的上下文管理器(可以在使用
池的其他地方重用):

终止
方法的优势在于它保证进程立即退出;理论上,如果您在主程序的其他地方使用线程,
工作线程可能与非守护进程线程分叉,这将使进程保持活动状态,即使工作任务线程退出<代码>终止
通过强制终止进程来隐藏这一点


如果您的解释器是Python 3.3或更高版本,则
终止方法内置于
池中,因此
with
语句,
with multiprocessing.Pool(initializer=initWorker,initargs=(globalData,)不需要特殊的包装器作为池:
直接起作用。

为真正的资本家标题投票可能您只需添加
try:。。。最后:pool.terminate()
?也许我的问题不清楚-我是说即使计算完成,工人们也会留下来。尽管他们不应该这样做,但如果我正确理解了文档,无论如何……我想了解更多正在发生的事情。但我会试试你的建议。
from contextlib import contextmanager

@contextmanager
def terminating(obj):
    try:
        yield obj
    finally:
        obj.terminate()

def computeStuff(arguments, globalData, concurrent=True):
    with terminating(multiprocessing.Pool(initializer=initWorker, initargs=(globalData,))) as pool:
        return pool.map(workerFunction, enumerate(arguments))