识别当前进程是Python中的子进程

时间:2015-06-30 20:11:15

标签: python python-multiprocessing

在Python 2.7中,有一种方法可以识别当前的forked / spawned进程是否是子进程实例(而不是作为常规进程启动)。我的目标是如果它是一个子进程,则设置一个不同的全局变量(例如,为其他具有大于0的数字的其他池创建一个大小为0的池)。

我无法将参数传递给函数(被调用以在子进程中执行),因为即使在调用函数之前,该进程也已经初始化,因此也是全局变量(特别是对于生成的进程)。 / p>

此外,由于我的应用程序在Web服务容器(flask)中运行,因此我无法使用freeze_support(当然,除非我很想知道如何使用它)。因此,没有主要方法。

非常感谢任何帮助。

如果在Windows上运行它,将进入无限循环的示例代码:

from multiprocessing import Pool, freeze_support

p = Pool(5) # This should be created only in parent process and not the child process

def f(x):
    return x*x

if __name__ == '__main__':
    freeze_support()
    print(p.map(f, [1, 2, 3]))

2 个答案:

答案 0 :(得分:2)

我建议将程序重构为更像下面的示例代码。您提到您没有main函数,但您可以创建一个处理池的包装器:

from multiprocessing import Pool, freeze_support

def f(x):
    return x*x


def handle_request():

    p = Pool(5) # pool will only be in the parent process

    print(p.map(f, [1, 2, 3]))

    p.close() # remember to clean up the resources you use
    p.join()

    return

if __name__ == '__main__':
    freeze_support() # do you really need this?

    # start your web service here and make it use `handle_request` as the callback
    # when a request needs to be serviced

听起来你有点XY problem。您不应该在全球范围内创建流程池。这很糟糕。你给你的子进程访问他们自己的进程对象,这允许你不小心做坏事,比如让子进程加入自己。如果在为每个请求调用的包装器中创建池,则无需担心全局变量。

在评论中,您提到过您需要一个持久池。在每个请求上创建池确实有一些开销,但它比拥有全局池更安全。此外,您现在可以同时处理多个请求,假设您的Web服务处理其自己的线程/进程中的每个请求,而没有多个请求通过尝试使用相同的池来相互欺骗。我强烈建议您尝试使用此方法,如果它不符合您的性能规范,您可以考虑以其他方式(即没有全局池)优化它以满足您的规范。

另一个注意事项:如果您打算将脚本捆绑到Windows可执行文件中,则只需要调用multiprocessing.freeze_support()。如果你不这样做,请不要使用它。

答案 1 :(得分:0)

将池创建移动到主要部分,只创建一个多处理池,只在主进程中创建一个:

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    p = Pool(5)
    print(p.map(f, [1, 2, 3]))

这是有效的,因为在__main__名称中执行的唯一进程是原始进程。生成的进程使用__mp_main__模块名称运行。

  

为孩子

创建一个大小为0的游泳池

子进程永远不应该启动新的多处理池。仅从单个入口点处理您的流程。