python脚本挂起导入模块与多处理代码

python script hangs on importing module with multiprocessing code

我正在尝试导入一个简单的模块,该模块使用多处理将主文件导入。使用多处理的模块从asyncresult.get()获得计算结果。当通过导入脚本调用此例程时,脚本将挂起且不继续。

下面是一个小例子。

import_test.py(要导入的模块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import sys
import multiprocessing as mp

if not hasattr(sys.stdin, 'close'):
    def dummy_close():
        pass
    sys.stdin.close = dummy_close

# simple test function to compute in parallel
def testf(x):
    return x*x

# multiprocessing code
pool = mp.Pool()
results = []
for i in range(0,2):
    results.append(pool.apply_async(testf, [i]))
for i in range(0,2):
    print results[i].get()
pool.close()
pool.join()

main.py(简单的脚本,只导入代码,应该打印import-test中的内容)

1
2
3
4
if __name__ == '__main__':
    import import_test

print"done"

运行脚本时,我可以看到导入发生了,但第一次调用results[i].get()(asyncresult.get()例程)时,整个脚本将挂起,并且不会在不引发任何错误的情况下继续。我在运行两个明显不同的python设置的mac os x(el capitan)和windows 10下测试过这个。结果总是如上所述的行为。

如果我将导入模块中的代码放入main.py本身,一切都会正常工作。当然,我的实际代码比这要复杂得多,我希望在要导入的模块中保持并行计算。

我如何解决这个问题?


我可能来的太晚了,但我想我能回答你的问题。我也有过同样的经历。这源于python在导入期间如何处理gil锁,以及它如何与多处理冲突,从而创建死锁。

您应该看看https://docs.python.org/2/library/imp.html。问题是:python在执行导入时获取gil锁,并在最后释放它。因此,当您在导入的模块中通过多处理运行一个线程,并且它需要获取锁时,就会发生死锁。这就是我建议您在主文件中进行多处理的原因。

如果出于某种原因,您绝对希望在导入期间进行多处理,那么还有一个解决方案:

1
2
3
4
5
 import imp
 if imp.lock_held():
     imp.release_lock()
     # do your multiprocessing stuff
     imp.acquire_lock() # Don't forget this import needs to have the lock acquired at the end of the import

如果不让imp重新获取锁,则会得到一个运行时异常。

我希望这对某人有所帮助。


有趣的是,当您将代码放在main.py中时,它可以正常工作。你能试着把你的代码转换成一个函数吗?按照现在的方式,一旦导入完成,代码就会被执行。这至少可以让您控制何时运行代码。

进口:

1
2
3
4
5
import sys
import multiprocessing as mp

def run():
    <your code>

在MY.PY:

1
2
3
if __name__ == '__main__':
    import import_test
    import_test.run()