我开始尝试与IPython的并行工具,并有一个问题。 我开始了我的蟒蛇发动机具有:
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],它应。 但是,如果我打破了代码转换成不同的文件:dop.py:
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
从IPython.parallel.util
[1]如果你希望它有机会获得发动机的全局命名空间:
from IPython.parallel.util import interactive
f = interactive(lambda x: a+b+x)
ack = dview.apply(f, x)
实际的解释:
IPython的用户命名空间是基本模块__main__
。 这是代码,当你运行execute('a = 5')
如果交互定义一个函数,它的模块也__main__
:
lam = lambda x: a+b+x
lam.__module__
'__main__'
当发动机unserializes的功能,但是这样做的对功能的模块选择合适的全局命名空间,所以在定义函数__main__
在客户端中也定义__main__
在发动机上,从而有机会获得a
。
一旦你把它放在一个文件,并将其导入,那么功能不再连接到__main__
,但模块dop
:
from dop import dop
dop.__module__
'dop'
所有的功能通常在该模块中定义(包括lambda表达式)都会有这个值,所以当他们解包的引擎的全局命名空间将是对的dop
模块, 不 __main__
,所以,您的一个不可访问。
出于这个原因,IPython中提供了一个简单@interactive
就好像它是在定义的被解压缩导致任何功能装饰__main__
,而不管该函数实际上是定义在何处。
对于差的一个例子,借此dop.py
:
from IPython.parallel import Client
from IPython.parallel.util import interactive
a = 1
def dop(x):
rc = Client()
dview = rc[:]
dview['a'] = 5
f = lambda x: a+x
return dview.apply_sync(f, x)
def idop(x):
rc = Client()
dview = rc[:]
dview['a'] = 5
f = interactive(lambda x: a+x)
return dview.apply_sync(f, x)
现在, dop
将使用“A”从DOP模块,并idop
将使用“A”从你的引擎命名空间。 两者之间的唯一区别是,通过应用功能被包裹在@interactive
:
from dop import dop, idop
print dop(5) # 6
print idop(5) # 10
[1]:在IPython中> = 0.13(即将发布), @interactive
也可作为from IPython.parallel import interactive
,它总是应该已经。