Python多进程:是否可以在池中嵌套一个池?

21

我有一个模块A,它通过将数据发送到模块B、C、D等进行分析,然后将它们的结果合并来进行基本的map/reduce操作。

但是似乎模块B、C、D等不能创建自己的多进程池,否则会出现

AssertionError: daemonic processes are not allowed to have children

有没有其他方法可以并行执行这些任务?

为了清晰起见,这里提供一个(确实很差的)示例。(我通常会使用try/catch,但您可以理解我的意思)。

A.py:

  import B
  from multiprocessing import Pool

  def main():
    p = Pool()
    results = p.map(B.foo,range(10))
    p.close()
    p.join()
    return results


B.py:
  
  from multiprocessing import Pool

  def foo(x):
    p = Pool()
    results = p.map(str,x)
    p.close()
    p.join()
    return results
1个回答

31

有没有可能在泳池里再建一个泳池?

是的,虽然可能不是个好主意,除非你想养一支僵尸军队。参考Python进程池是否是守护进程?:

import multiprocessing.pool
from contextlib import closing
from functools import partial

class NoDaemonProcess(multiprocessing.Process):
    # make 'daemon' attribute always return False
    def _get_daemon(self):
        return False
    def _set_daemon(self, value):
        pass
    daemon = property(_get_daemon, _set_daemon)

# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class Pool(multiprocessing.pool.Pool):
    Process = NoDaemonProcess

def foo(x, depth=0):
    if depth == 0:
        return x
    else:
        with closing(Pool()) as p:
            return p.map(partial(foo, depth=depth-1), range(x + 1))

if __name__ == "__main__":
    from pprint import pprint
    pprint(foo(10, depth=2))

输出

[[0],
 [0, 1],
 [0, 1, 2],
 [0, 1, 2, 3],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4, 5],
 [0, 1, 2, 3, 4, 5, 6],
 [0, 1, 2, 3, 4, 5, 6, 7],
 [0, 1, 2, 3, 4, 5, 6, 7, 8],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

concurrent.futures 默认支持它:

# $ pip install futures # on Python 2
from concurrent.futures import ProcessPoolExecutor as Pool
from functools import partial

def foo(x, depth=0):
    if depth == 0:
        return x
    else:
        with Pool() as p:
            return list(p.map(partial(foo, depth=depth-1), range(x + 1)))

if __name__ == "__main__":
    from pprint import pprint
    pprint(foo(10, depth=2))

它产生相同的输出。

有没有其他方法可以并行执行这些任务?

有。例如,看看celery如何允许创建复杂的工作流程


感谢您指出futures默认支持它。 - satoru
什么是僵尸军团? - Frank Meulenaar
@FrankMeulenaar:什么是“<defunct>”进程,为什么它不能被杀死?(https://askubuntu.com/a/427222/3712) - jfs
@jfs:好的,你最初的回答链接到了一封Python邮件讨论,我没有看出与僵尸的联系。 - Frank Meulenaar
@FrankMeulenaar:我已经修复了链接。 - jfs
显示剩余2条评论

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