语境
在连接到集群的笔记本上的交互式原型开发中,我想定义一个在客户端__main__
会话中可用并在集群引擎节点上交互式更新的类,以便能够通过传递此类实例来移动该类的实例LoadBalanced 视图的参数。下面演示了典型的用户会话:
首先设置并行集群环境:
>>> from IPython.parallel import Client
>>> rc = Client()
>>> lview = rc.load_balanced_view()
>>> rc[:]
<DirectView [0, 1, 2]>
在笔记本单元格中,让我们定义我们正在交互编辑的组件的代码片段:
>>> class MyClass(object):
... def __init__(self, parameter):
... self.parameter = parameter
...
... def update_something(self, some_data):
... # do something smart here with some_data & internal state
...
... def compute_something(self, other_data):
... # do something smart here with other data & internal state
... return something
...
在下一个单元格中,让我们创建一个构建此类实例的脚本,然后使用集群环境的负载平衡视图在各种输入参数上评估我们的组件:
>>> def process(obj, some_data, other_data):
... obj.update_something(some_data)
... return obj.compute_something(other_data)
...
>>> tasks = []
>>> some_instances = [MyClass(i) for i in range(10)]
>>> for obj in some_instances:
... for some_data in data_source_1:
... for other_data in data_source_2:
... ar = lview.apply_async(process, obj, some_data, other_data)
... tasks.append(ar)
...
>>> # wait for computation to end
>>> results = [ar.get() for ar in tasks]
问题
这显然不起作用,因为负载平衡视图的引擎将无法解开作为第一个参数传递给process
函数的实例。进程函数定义本身已成功传递,因为我假设apply_async
执行字节码自省来腌制它(通过访问.code
函数的属性),然后只对剩余的参数进行简单的腌制。
可能的解决方案(对我不起作用)
一种替代解决方案是在
%%px
保存类定义的单元格上使用单元格魔法MyClass
。但是,这将阻止我在客户端脚本中构建也执行调度的类实例。我需要在没有魔法的情况下将单元格内容复制并粘贴到另一个单元格中%%px
(或者使用魔法执行单元格两次,然后再次使用魔法执行单元格)但是当我仍在迭代中编辑类的方法时,这很乏味开发和评估设置。另一种解决方案是将类定义嵌入
process
函数中,但我发现这不切实际,因为我想稍后在我的笔记本中的其他函数中重用该类定义。或者,我可以停止使用一个类,而只使用可以通过将 then 作为第一个参数传递给引擎的函数
apply_async
。但是我也不喜欢这样,因为我想以面向对象的方式对我的代码进行原型设计,以便以后从笔记本中提取并将生成的类包含在面向对象的库中。笔记本会话用作协作原型工具,用于使用http://nbviewer.ipython.org发布者在开发人员之间交换想法。最后的替代方法是在文件系统上的文件上的 python 模块中编写我的类,然后使用 NFS 将该文件发送到引擎 PYTHONPATH。这有效,但阻止我只在笔记本环境中工作,这违背了笔记本中交互式原型设计的全部目的。
所以基本上,有没有办法以交互方式定义一个类,然后将它的定义发送到引擎?
应该可以inspect.getsource
在客户端中使用 pickle 类定义,然后将源发送到引擎并使用eval
内置但不幸的是源检查不适用于DummyMod
内置模块中定义的类:
TypeError: <IPython.core.interactiveshell.DummyMod object at 0x10c2c4e50> is a built-in class
有没有办法检查类定义的字节码?
或者是否可以使用%%px
魔法在客户端和每个引擎上本地执行单元格的内容?