1

我有一个使用multiprocessing. 我正在使用另一个脚本执行此模块runpy。但是,这会导致 (1) 模块运行两次,以及 (2)multiprocessing作业永远不会完成(脚本只是挂起)。

在我的最小工作示例中,我有一个脚本runpy_test.py

import runpy
runpy.run_module('module_test')

和一个目录module_test包含一个空的__init__.py和一个__main__.py

from multiprocessing import Pool

print 'start'
def f(x):
    return x*x
pool = Pool()
result = pool.map(f, [1,2,3])
print 'done'

当我运行runpy_test.py时,我得到:

start
start

脚本挂起。

如果我删除pool.map调用(或者如果我直接运行__main__.py,包括pool.map调用),我会得到:

start
done

我在 Python 2.7.5 中的 Scientific Linux 7.6 上运行它。

4

3 回答 3

1

像这样重写你的__main__.py

from multiprocessing import Pool
from .implementation import f

print 'start'
pool = Pool()
result = pool.map(f, [1,2,3])
print 'done'

然后编写一个implementation.py(你可以随意调用它)来定义你的函数:

def f(x):
    return x*x

否则,您将在多处理中的大多数接口上遇到相同的问题,并且与使用 runpy 无关。正如@Weeble 解释的那样,当Pool.map尝试f在每个子进程中加载​​函数时,它将导入<your_package>.__main__定义函数的位置,但是由于您在模块级别具有可执行代码,__main__因此子进程将重新执行它。

除了这个技术原因,这在关注点分离和测试方面也是更好的设计。现在您可以轻松地导入和调用(包括用于测试目的)该函数f,而无需并行运行它。

于 2019-10-08T15:15:13.967 回答
1

尝试f在单独的模块中定义您的函数。它需要被序列化以传递给池进程,然后这些进程需要通过导入它所在的模块来重新创建它。但是,__main__.py它所在的文件不是模块,或者至少不是井——乖乖的。尝试导入它会导致创建另一个 Pool 和另一个 map 调用,这似乎是灾难的根源。

于 2019-10-08T15:06:19.383 回答
0

虽然不是“正确”的方法,但最终为我工作的一种解决方案是使用 runpy's_run_module_as_main而不是run_module. 这对我来说非常理想,因为我正在使用其他人的代码并且需要最少的更改。

于 2019-10-08T15:55:25.170 回答