为什么Python Multiprocessing Worker不会死?

Ant*_*t6n 10 python pypy python-multiprocessing

我正在使用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
Run Code Online (Sandbox Code Playgroud)

通常我使用cPython和Pypy在ipython中运行测试.我注意到产生的过程通常不会被杀死,所以它们开始积累,每个都使用一个ram.在计算过程中按ctrl-k会发生这种情况,这会将多处理发送到混乱的大狂热中.但即使让计算完成,这些过程也不会在Pypy中死亡.

根据文档,当池被垃圾收集时,它应该调用terminate()并终止所有进程.这里发生了什么事?我必须明确打电话close()吗?如果是,是否有某种上下文管理器可以正确管理关闭资源(即进程)?

这是在Mac OS X Yosemite上.

Sha*_*ger 4

PyPy 的垃圾收集是惰性的,因此未能调用close意味着Pool“有时”会被清理,但这可能并不意味着“很快”。

一旦Pool正确close完成任务,工作人员就会在任务耗尽时退出。确保Pool在 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))
Run Code Online (Sandbox Code Playgroud)

注意:我还删除了显式转换为list(毫无意义,因为map将为您迭代enumerate迭代器),并直接返回结果(无需分配一个名称,仅在下一行返回)。

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

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))
Run Code Online (Sandbox Code Playgroud)

terminating方法的优越性在于它保证进程立即退出;理论上,如果您在主程序的其他地方使用线程,Pool工作线程可能会被非守护线程分叉,即使工作任务线程退出,这也会使进程保持活动状态;terminating通过强制终止进程来隐藏这一点。

如果您的解释器是Python 3.3或更高版本,则该terminating方法是内置的Pool,因此该语句不需要特殊的包装器withwith multiprocessing.Pool(initializer=initWorker, initargs=(globalData,)) as pool:可以直接工作。