我开始尝试使用ipython并行工具,并遇到了一个问题。我启动python引擎时使用:

ipcluster start -n 3

然后以下代码运行正常:
from IPython.parallel import Client

def dop(x):
    rc = Client()
    dview = rc[:]
    dview.block=True
    dview.execute('a = 5')
    dview['b'] = 10
    ack = dview.apply(lambda x: a+b+x, x)
    return ack

ack = dop(27)
print ack

按原样返回[42,42,42]。但是如果我把代码分解成不同的文件:
打印日期:
from IPython.parallel import Client

def dop(x):
    rc = Client()
    dview = rc[:]
    dview.block=True
    dview.execute('a = 5')
    dview['b'] = 10
    print dview['a']
    ack = dview.apply(lambda x: a+b+x, x)
    return ack

并尝试以下操作:
from dop import dop
ack = dop(27)
print ack

我从每个引擎得到错误:
[0:apply]: NameError: global name 'a' is not defined
[1:apply]: NameError: global name 'a' is not defined
[2:apply]: NameError: global name 'a' is not defined

我不明白……为什么我不能把函数放在另一个文件中并导入它?

最佳答案

快速回答:如果您希望函数能够访问引擎的全局命名空间,请使用来自@interactive[1]的IPython.parallel.util来修饰您的函数:
从ipython.parallel.util导入Interactive
F=交互式(lambda x:a+b+x)
ACK=D视图应用(F,X)
实际解释:
ipython用户名称空间本质上是模块__main__。这是在执行execute('a = 5')时运行代码的地方。
如果以交互方式定义函数,则其模块也为:
lam=lambda x:a+b+x
激光模组__
'主'
当引擎取消对某个函数的序列化时,它会在函数模块的相应全局命名空间中进行此操作,因此在客户端的__main__中定义的函数也会在引擎的__main__中定义,因此可以访问__main__
一旦将其放入文件并导入,那么函数就不再附加到a中,而是模块__main__
从DOP导入DOP
DOP模块__
“DOP”
该模块(包括lambda)中常规定义的所有函数都将具有此值,因此当在引擎上解包它们时,它们的全局命名空间将是dop模块的全局命名空间,而不是dop,因此您的“a”不可访问。
因此,ipython提供了一个简单的__main__修饰器,它可以像在@interactive中定义的那样对任何函数进行解包,而不管函数实际上是在哪里定义的。
对于差异的一个例子,请看下面的例子:
来自ipython.parallel导入客户端
从ipython.parallel.util导入Interactive
A=1
定义DOP(X):
rc=客户机()
dView=rc[:]
视图[‘A’]=5
F=λx:a+x
返回dview.应用同步(f,x)
定义IDOP(X):
rc=客户机()
dView=rc[:]
视图[‘A’]=5
F=交互式(lambda x:a+x)
返回dview.应用同步(f,x)
现在,__main__将使用dop模块中的“a”,dop.py将使用引擎名称空间中的“a”。两者之间的唯一区别是传递给apply的函数被包装在dop中:
从DOP导入DOP,IDOP
打印DOP(5)6
打印IDOP(5)10
[1]:在ipython>=0.13(即将发布的版本)中,idop也可以作为@interactive提供,在这里它应该一直存在。

07-26 09:11