可以创建一个非守护进程的python池吗?我希望一个池能够调用内部有另一个池的函数。
我之所以需要它,是因为守护进程不能创建进程。具体来说,它会导致以下错误:
AssertionError: daemonic processes are not allowed to have children例如,考虑这样一个场景:function_a有一个运行function_b的池,而这个池又有一个运行function_c的池。此函数链将失败,因为function_b正在守护进程中运行,并且守护进程无法创建进程。
发布于 2012-01-23 02:46:24
multiprocessing.pool.Pool类在其__init__方法中创建工作进程,使其成为守护进程并启动它们,并且在它们启动之前不能将它们的daemon属性重新设置为False (之后就不允许这样做了)。但是您可以创建自己的multiprocesing.pool.Pool子类(multiprocessing.Pool只是一个包装器函数),并替换为您自己的multiprocessing.Process子类,它总是非守护进程,用于工作进程。
这里有一个完整的例子来说明如何做到这一点。重要的部分是顶部的两个类NoDaemonProcess和MyPool,以及最后在MyPool实例上调用pool.close()和pool.join()。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import multiprocessing
# We must import this explicitly, it is not imported by the top-level
# multiprocessing module.
import multiprocessing.pool
import time
from random import randint
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 MyPool(multiprocessing.pool.Pool):
Process = NoDaemonProcess
def sleepawhile(t):
print("Sleeping %i seconds..." % t)
time.sleep(t)
return t
def work(num_procs):
print("Creating %i (daemon) workers and jobs in child." % num_procs)
pool = multiprocessing.Pool(num_procs)
result = pool.map(sleepawhile,
[randint(1, 5) for x in range(num_procs)])
# The following is not really needed, since the (daemon) workers of the
# child's pool are killed when the child is terminated, but it's good
# practice to cleanup after ourselves anyway.
pool.close()
pool.join()
return result
def test():
print("Creating 5 (non-daemon) workers and jobs in main process.")
pool = MyPool(5)
result = pool.map(work, [randint(1, 5) for x in range(5)])
pool.close()
pool.join()
print(result)
if __name__ == '__main__':
test()发布于 2018-11-07 06:16:27
我有必要在Python3.7中使用非守护程序池,并最终修改了发布在公认答案中的代码。下面是创建非守护程序池的代码片段:
import multiprocessing.pool
class NoDaemonProcess(multiprocessing.Process):
@property
def daemon(self):
return False
@daemon.setter
def daemon(self, value):
pass
class NoDaemonContext(type(multiprocessing.get_context())):
Process = NoDaemonProcess
# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class NestablePool(multiprocessing.pool.Pool):
def __init__(self, *args, **kwargs):
kwargs['context'] = NoDaemonContext()
super(NestablePool, self).__init__(*args, **kwargs)由于当前的multiprocessing实现已经被广泛重构为基于上下文,因此我们需要提供一个将NoDaemonProcess作为属性的NoDaemonContext类。然后,NestablePool将使用该上下文而不是默认上下文。
这就是说,我应该警告,这种方法至少有两个警告:
multiprocessing包的实现细节,因此可能会在任何时候中断。multiprocessing让非守护进程变得如此困难是有正当理由的,其中许多都在here中解释过。在我看来,最引人注目的是:对于允许子线程使用子进程派生自己的子线程,如果父线程或子线程在子进程完成并返回之前终止,则可能会产生一小群僵尸“孙子线程”。
发布于 2015-12-03 22:50:21
multiprocessing模块有一个很好的接口,可以将池与进程、或线程一起使用。根据您当前的用例,您可能会考虑对外部池使用multiprocessing.pool.ThreadPool,这将导致线程(允许从内部派生进程)而不是进程。
它可能会受到GIL的限制,但在我的特殊情况下(我对两者都进行了测试),从外部Pool创建的here进程的启动时间远远超过了使用ThreadPool的解决方案。
用Threads替换Processes真的很容易。阅读有关如何使用ThreadPool解决方案here或here的更多信息。
https://stackoverflow.com/questions/6974695
复制相似问题