2014-10-31 63 views
3

我試圖遵循一個非常簡單的多例子:Python的多apply_async永遠不會返回在Windows 7的結果

import multiprocessing as mp 

def cube(x): 
    return x**3 

pool = mp.Pool(processes=2) 
results = [pool.apply_async(cube, args=x) for x in range(1,7)] 

然而,我的Windows機器上,我無法得到的結果(在Ubuntu 12.04LTS它完美運行)。

如果我檢查results,我看到以下內容:

[<multiprocessing.pool.ApplyResult object at 0x01FF0910>, 
<multiprocessing.pool.ApplyResult object at 0x01FF0950>, 
<multiprocessing.pool.ApplyResult object at 0x01FF0990>, 
<multiprocessing.pool.ApplyResult object at 0x01FF09D0>, 
<multiprocessing.pool.ApplyResult object at 0x01FF0A10>, 
<multiprocessing.pool.ApplyResult object at 0x01FF0A50>] 

如果我跑results[0].ready()我總是False

如果我運行results[0].get() python解釋器凍結,等待得到的結果永遠不會到來。

這個例子非常簡單,所以我認爲這是一個與OS有關的低級錯誤(我在Windows 7上)。但也許別人有更好的主意?

+1

'multiprocessing'在交互式Python解釋器中不能很好地工作。當您將此代碼作爲腳本運行時,它是否有效? – 2014-10-31 17:50:17

+0

@moarningsun它在腳本中也不起作用。達諾的解決方案取得了訣竅 – kyphos 2014-10-31 17:54:43

回答

10

這裏有幾個錯誤。首先,您必須在if __name__ == "__main__":後衛when running on Windows內聲明Pool。其次,即使只傳遞一個參數,也必須將args關鍵字參數傳遞給一個序列。所以把它們一起:

import multiprocessing as mp 

def cube(x): 
    return x**3 

if __name__ == "__main__": 
    pool = mp.Pool(processes=2) 
    results = [pool.apply_async(cube, args=(x,)) for x in range(1,7)] 
    print([result.get() for result in results]) 

輸出:

[1, 8, 27, 64, 125, 216] 

編輯:

哦,爲moarningsun提到,multiprocessingdoes not work well在交互式解釋:

該軟件包內的功能要求__main__模塊爲 可由孩子導入。這在編程指南 中有介紹,但值得在此指出。這意味着一些示例 (如multiprocessing.Pool示例)不會在 交互式解釋器中工作。

所以你需要實際執行代碼作爲腳本來正確地測試它。

3

我正在運行python 3,IDE是anaconda(windows)中的spyder,所以這個技巧對我來說不起作用。我嘗試了很多,但沒有任何區別。我得到了我的問題的原因,並在他的筆記中由dano列出。但經過漫長的一天搜索,我得到了一些解決方案,它幫助我運行相同的代碼我的Windows機器。這個網站幫助我獲得瞭解決方案:

http://python.6.x6.nabble.com/Multiprocessing-Pool-woes-td5047050.html

自從我使用Python 3,我改變了計劃有點像這樣:

from types import FunctionType 
import marshal 

def _applicable(*args, **kwargs): 
    name = kwargs['__pw_name'] 
    code = marshal.loads(kwargs['__pw_code']) 
    gbls = globals() #gbls = marshal.loads(kwargs['__pw_gbls']) 
    defs = marshal.loads(kwargs['__pw_defs']) 
    clsr = marshal.loads(kwargs['__pw_clsr']) 
    fdct = marshal.loads(kwargs['__pw_fdct']) 
    func = FunctionType(code, gbls, name, defs, clsr) 
    func.fdct = fdct 
    del kwargs['__pw_name'] 
    del kwargs['__pw_code'] 
    del kwargs['__pw_defs'] 
    del kwargs['__pw_clsr'] 
    del kwargs['__pw_fdct'] 
    return func(*args, **kwargs) 

def make_applicable(f, *args, **kwargs): 
    if not isinstance(f, FunctionType): raise ValueError('argument must be a function') 
    kwargs['__pw_name'] = f.__name__ # edited 
    kwargs['__pw_code'] = marshal.dumps(f.__code__) # edited 
    kwargs['__pw_defs'] = marshal.dumps(f.__defaults__) # edited 
    kwargs['__pw_clsr'] = marshal.dumps(f.__closure__) # edited 
    kwargs['__pw_fdct'] = marshal.dumps(f.__dict__) # edited 
    return _applicable, args, kwargs 

def _mappable(x): 
    x,name,code,defs,clsr,fdct = x 
    code = marshal.loads(code) 
    gbls = globals() #gbls = marshal.loads(gbls) 
    defs = marshal.loads(defs) 
    clsr = marshal.loads(clsr) 
    fdct = marshal.loads(fdct) 
    func = FunctionType(code, gbls, name, defs, clsr) 
    func.fdct = fdct 
    return func(x) 

def make_mappable(f, iterable): 
    if not isinstance(f, FunctionType): raise ValueError('argument must be a function') 
    name = f.__name__ # edited 
    code = marshal.dumps(f.__code__) # edited 
    defs = marshal.dumps(f.__defaults__) # edited 
    clsr = marshal.dumps(f.__closure__) # edited 
    fdct = marshal.dumps(f.__dict__) # edited 
    return _mappable, ((i,name,code,defs,clsr,fdct) for i in iterable) 

此功能後,上述問題的代碼也改變有點像這樣:

from multiprocessing import Pool 
from poolable import make_applicable, make_mappable 

def cube(x): 
    return x**3 

if __name__ == "__main__": 
    pool = Pool(processes=2) 
    results = [pool.apply_async(*make_applicable(cube,x)) for x in range(1,7)] 
    print([result.get(timeout=10) for result in results]) 

而且我得到的輸出:

[1, 8, 27, 64, 125, 216] 

我在想這個帖子可能對一些windows用戶有用。

相關問題