2013-09-05 124 views
5

我想写测试nose,得到的东西 设置使用多处理计算。测试蟒蛇多处理池鼻子的代码

我有这样的目录结构:

code/ 
    tests/ 
     tests.py 

tests.py看起来是这样的:

import multiprocessing as mp 


def f(i): 
    return i ** 2 


pool = mp.Pool() 
out = pool.map(f, range(10)) 


def test_pool(): 
    """Really simple test that relies on the output of pool.map. 
    The actual tests are much more complicated, but this is all 
    that is needed to produce the problem.""" 
    ref_out = map(f, range(10)) 
    assert out == ref_out 

if __name__ == '__main__': 
    test_pool() 

code目录中运行,python tests/tests.py通过

nosetests tests/tests.py失败来完成。它启动,但从来没有通过呼叫pool.map,只是挂起。

为什么这是最简单的解决方案?

+0

这可能是'nose'使用一些线程和/或运行时,记录试验。当*在UNIX系统上与多重处理混合时,*会导致死锁。这不是python实现的问题,而是使用'fork()'函数本身,它只分析当前线程,请参阅[this](http://stackoverflow.com/questions/6078712/is-it-safe-to -for-within-a-thread/6079669#6079669)回答更详细的解释。 – Bakuriu

+0

我相信唯一的(?)解决方案就是模拟'multiprocessing'模块。事实上,我没有看到你的例子正在测试什么。它实际上是'multiprocessing.Pool.map'方法的单元测试,而不是'f'函数! – Bakuriu

+0

这是最小的例子,再现我的错误。我正在测试一些使用'pool.map'的结果作为输入的其他东西。 – aaren

回答

4

该问题与pool.map被称为“全球级”的事实有关。通常你想避免这种情况,因为即使你的文件被简单地导入,这些语句也会被执行。

鼻子必须import your module能够找到您的测试,并稍后执行它们,因此我相信问题发生在导入机制启动时(我没有花时间试图找出此行为的确切原因)

您应该将初始化代码移动到测试夹具上;鼻子支持与装饰者with_setup装置。这是一种可能性(可能同时保持poolout作为全局最简单的变化):

import multiprocessing as mp 
from nose import with_setup 

pool = None 
out = None 

def f(i): 
    return i ** 2 

def setup_func(): 
    global pool 
    global out 
    pool = mp.Pool() 
    out = pool.map(f, range(10)) 

@with_setup(setup_func) 
def test_pool(): 
    """Really simple test that relies on the output of pool.map. 
    The actual tests are much more complicated, but this is all 
    that is needed to produce the problem.""" 
    global out 
    ref_out = map(f, range(10)) 
    assert out == ref_out 

if __name__ == '__main__': 
    test_pool() 

执行:

$ nosetests tests/tests.py 
. 
---------------------------------------------------------------------- 
Ran 1 test in 0.011s 

OK