2013-09-05 119 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