确定当前进程是 Python 中的子进程
Identify current process is child process in Python
在 Python 2.7 中,是否有一种方法可以识别当前 forked/spawned 进程是否为子进程实例(而不是作为常规进程启动)。如果它是子进程,我的目标是设置一个不同的全局变量(例如,为子进程创建一个大小为 0 的池,其他池的一些数字大于 0)。
我无法将参数传递给函数(被调用以在子进程中执行),因为即使在调用函数之前,进程也会被初始化,因此全局变量(特别是对于生成的进程) .
此外,我无法使用 freeze_support(当然,除非我不了解如何使用它)因为我的应用程序 运行 在 Web 服务容器(烧瓶)中.因此没有main方法。
任何帮助将不胜感激。
如果您 运行 在 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]))
将池创建移动到主要部分以仅创建一次多处理池,任何仅在主进程中:
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__
模块名称生成的进程 运行。
create a pool with size 0 for child
子进程永远不应启动新的多处理池。仅从单个入口点处理您的流程。
我建议将您的程序重组为更类似于我下面的示例代码的内容。您提到您没有 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 服务在它们自己的 thread/process 中处理每个请求,而不会有多个请求通过尝试使用同一个池而相互践踏。我强烈建议您尝试使用这种方法,如果它不符合您的性能规范,您可以考虑以其他方式对其进行优化(即,没有全局池)以满足您的规范。
另一个注意事项:只有在您打算将脚本捆绑到 Windows 可执行文件中时才需要调用 multiprocessing.freeze_support()。如果您不这样做,请不要使用它。
在 Python 2.7 中,是否有一种方法可以识别当前 forked/spawned 进程是否为子进程实例(而不是作为常规进程启动)。如果它是子进程,我的目标是设置一个不同的全局变量(例如,为子进程创建一个大小为 0 的池,其他池的一些数字大于 0)。
我无法将参数传递给函数(被调用以在子进程中执行),因为即使在调用函数之前,进程也会被初始化,因此全局变量(特别是对于生成的进程) .
此外,我无法使用 freeze_support(当然,除非我不了解如何使用它)因为我的应用程序 运行 在 Web 服务容器(烧瓶)中.因此没有main方法。
任何帮助将不胜感激。
如果您 运行 在 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]))
将池创建移动到主要部分以仅创建一次多处理池,任何仅在主进程中:
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__
模块名称生成的进程 运行。
create a pool with size 0 for child
子进程永远不应启动新的多处理池。仅从单个入口点处理您的流程。
我建议将您的程序重组为更类似于我下面的示例代码的内容。您提到您没有 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 服务在它们自己的 thread/process 中处理每个请求,而不会有多个请求通过尝试使用同一个池而相互践踏。我强烈建议您尝试使用这种方法,如果它不符合您的性能规范,您可以考虑以其他方式对其进行优化(即,没有全局池)以满足您的规范。
另一个注意事项:只有在您打算将脚本捆绑到 Windows 可执行文件中时才需要调用 multiprocessing.freeze_support()。如果您不这样做,请不要使用它。