在 runpy 中使用多处理
Using multiprocessing with runpy
我有一个使用 multiprocessing
的 Python 模块。我正在使用 runpy
从另一个脚本执行此模块。但是,这会导致 (1) 模块 运行ning 两次 ,以及 (2) multiprocessing
作业永远不会完成(脚本只是挂起)。
在我的最小工作示例中,我有一个脚本 runpy_test.py:
import runpy
runpy.run_module('module_test')
和一个包含空 __init__.py 和 [= 的目录 module_test 49=]:
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
我在 运行Scientific Linux 7.6 in Python 2.7.5.
尝试在单独的模块中定义函数 f
。它需要被序列化以传递给池进程,然后那些进程需要通过导入它出现的模块来重新创建它。但是,它出现的 __main__.py
文件不是模块,或者在至少,不是一个乖巧的人。尝试导入它会导致创建另一个池和另一个映射调用,这似乎是灾难的根源。
像这样重写你的__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
而无需并行 运行 它。
虽然不是 "right" 的方法,但最终对我有用的一种解决方案是使用 runpy 的 _run_module_as_main
而不是 run_module
。这对我来说非常理想,因为我正在使用其他人的代码并且需要最少的更改。
我有一个使用 multiprocessing
的 Python 模块。我正在使用 runpy
从另一个脚本执行此模块。但是,这会导致 (1) 模块 运行ning 两次 ,以及 (2) multiprocessing
作业永远不会完成(脚本只是挂起)。
在我的最小工作示例中,我有一个脚本 runpy_test.py:
import runpy
runpy.run_module('module_test')
和一个包含空 __init__.py 和 [= 的目录 module_test 49=]:
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
我在 运行Scientific Linux 7.6 in Python 2.7.5.
尝试在单独的模块中定义函数 f
。它需要被序列化以传递给池进程,然后那些进程需要通过导入它出现的模块来重新创建它。但是,它出现的 __main__.py
文件不是模块,或者在至少,不是一个乖巧的人。尝试导入它会导致创建另一个池和另一个映射调用,这似乎是灾难的根源。
像这样重写你的__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
而无需并行 运行 它。
虽然不是 "right" 的方法,但最终对我有用的一种解决方案是使用 runpy 的 _run_module_as_main
而不是 run_module
。这对我来说非常理想,因为我正在使用其他人的代码并且需要最少的更改。