首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python进程池不是守护进程?

Python进程池不是守护进程?
EN

Stack Overflow用户
提问于 2011-08-08 02:08:04
回答 8查看 62.8K关注 0票数 122

可以创建一个非守护进程的python池吗?我希望一个池能够调用内部有另一个池的函数。

我之所以需要它,是因为守护进程不能创建进程。具体来说,它会导致以下错误:

代码语言:javascript
复制
AssertionError: daemonic processes are not allowed to have children

例如,考虑这样一个场景:function_a有一个运行function_b的池,而这个池又有一个运行function_c的池。此函数链将失败,因为function_b正在守护进程中运行,并且守护进程无法创建进程。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-01-23 02:46:24

multiprocessing.pool.Pool类在其__init__方法中创建工作进程,使其成为守护进程并启动它们,并且在它们启动之前不能将它们的daemon属性重新设置为False (之后就不允许这样做了)。但是您可以创建自己的multiprocesing.pool.Pool子类(multiprocessing.Pool只是一个包装器函数),并替换为您自己的multiprocessing.Process子类,它总是非守护进程,用于工作进程。

这里有一个完整的例子来说明如何做到这一点。重要的部分是顶部的两个类NoDaemonProcessMyPool,以及最后在MyPool实例上调用pool.close()pool.join()

代码语言:javascript
复制
#!/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()
票数 136
EN

Stack Overflow用户

发布于 2018-11-07 06:16:27

我有必要在Python3.7中使用非守护程序池,并最终修改了发布在公认答案中的代码。下面是创建非守护程序池的代码片段:

代码语言:javascript
复制
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将使用该上下文而不是默认上下文。

这就是说,我应该警告,这种方法至少有两个警告:

  1. 它仍然依赖于multiprocessing包的实现细节,因此可能会在任何时候中断。
  2. multiprocessing让非守护进程变得如此困难是有正当理由的,其中许多都在here中解释过。在我看来,最引人注目的是:

对于允许子线程使用子进程派生自己的子线程,如果父线程或子线程在子进程完成并返回之前终止,则可能会产生一小群僵尸“孙子线程”。

票数 41
EN

Stack Overflow用户

发布于 2015-12-03 22:50:21

multiprocessing模块有一个很好的接口,可以将池与进程、线程一起使用。根据您当前的用例,您可能会考虑对外部池使用multiprocessing.pool.ThreadPool,这将导致线程(允许从内部派生进程)而不是进程。

它可能会受到GIL的限制,但在我的特殊情况下(我对两者都进行了测试),从外部Pool创建的here进程的启动时间远远超过了使用ThreadPool的解决方案。

Threads替换Processes真的很容易。阅读有关如何使用ThreadPool解决方案herehere的更多信息。

票数 27
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6974695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档