2014-10-31 94 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用户有用。

相关问题