如何在IPython.parallel中使用交互式定义的类? 上下文

如何在IPython.parallel中使用交互式定义的类? 上下文,python,parallel-processing,ipython,ipython-notebook,Python,Parallel Processing,Ipython,Ipython Notebook,在连接到集群的笔记本上的交互式原型开发中,我想定义一个类,该类既可以在客户端\uuuuu main\uuuuu会话中使用,也可以在集群引擎节点上进行交互式更新,以便能够通过将此类实例的参数传递给LoadBalanced视图来移动该类的实例。下面演示了典型的用户会话: 首先设置并行群集环境: >>> from IPython.parallel import Client >>> rc = Client() >>> lview = rc.load

在连接到集群的笔记本上的交互式原型开发中,我想定义一个类,该类既可以在客户端
\uuuuu main\uuuuu
会话中使用,也可以在集群引擎节点上进行交互式更新,以便能够通过将此类实例的参数传递给LoadBalanced视图来移动该类的实例。下面演示了典型的用户会话:

首先设置并行群集环境:

>>> from IPython.parallel import Client
>>> rc = Client()
>>> lview = rc.load_balanced_view()
>>> rc[:]
<DirectView [0, 1, 2]>
在下一个单元中,让我们创建一个脚本,用于构建此类的实例,然后使用集群环境的负载平衡视图,在广泛的输入参数上评估我们的组件:

>>> 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] 
问题 这显然不起作用,因为负载平衡视图的引擎将无法取消拾取作为第一个参数传递给
进程
函数的实例。进程函数定义本身被成功传递,因为我假设
apply\u async
执行字节码指令透视来pickle它(通过访问函数的
.code
属性),然后只对其余参数执行简单的pickle

可能的解决方案(对我不起作用)
  • 另一种解决方案是在包含类定义的单元格上使用
    %%px
    单元格魔术。然而,这将阻止我在客户端脚本中构建同样执行调度的类实例。我需要在没有
    %%px
    magic的其他单元格中复制并粘贴单元格内容(或者使用magic执行单元格两次,一次使用magic,另一次不使用magic),但当我仍然在迭代开发和评估设置中编辑类的方法时,这是很乏味的

  • 另一种解决方案是将类定义嵌入
    进程
    函数中,但我发现这不实用,因为我希望稍后在我的笔记本中的其他函数中重用该类定义

  • 或者,我可以停止使用一个类,只使用可以通过将then作为第一个参数传递给
    apply\u async
    传递给引擎的函数。然而,我也不喜欢这样,因为我想以面向对象的方式对我的代码进行原型化,以便以后从笔记本中提取,并将生成的类包含在面向对象库中。笔记本会话用作协作原型工具,用于在使用发布者的开发人员之间交换想法

  • 最后一种选择是在文件系统上的一个文件上的python模块中编写我的类,并使用NFS将该文件发送到引擎PYTHONPATH。这是可行的,但我不能只在笔记本电脑环境中工作,这违背了笔记本电脑中交互式原型设计的全部目的

那么基本上,有没有一种方法可以交互地定义一个类,然后将它的定义传递给引擎

应该可以在客户端中使用
inspect.getsource
对类定义进行pickle,然后将源发送到引擎并使用
eval
内置项,但不幸的是,源代码检查不适用于
dummyd
内置模块中定义的类:


TypeError:是一个内置类

有没有办法检查类定义的字节码


或者可以使用
%%px
魔术在客户端和每个引擎上本地执行单元格内容吗?

谢谢你的详细提问(并在Twitter上ping我)

首先,也许它应该被认为是一个bug,你不能仅仅推送类, 因为简单的解决方案应该是

rc[:]['MyClass'] = MyClass
但是,pickle交互定义的类只会产生一个引用(
“\x80\x02c\uuuuuuu main\uuuuuu\nq\x01.”
),给出DummyMod AttributeError。 这可能在IPython的序列化中内部修复

不过,这是一个实际可行的解决方案

将本地执行添加到
%%px
非常简单,只需:

def pxlocal(line, cell):
    ip = get_ipython()
    ip.run_cell_magic("px", line, cell)
    ip.run_cell(cell)
get_ipython().register_magic_function(pxlocal, "cell")
现在您有了一个
%%pxlocal
魔术,除了在本地运行单元外,它还运行
%%px

那么你所要做的就是:

%%pxlocal

class MyClass(object):
    # etc
在任何地方定义类。 我将向
%%px
添加一个
--local
标志,因此不需要执行此额外步骤

一个完整的、有效的。

我认为您可以使用“dill”来pickle交互式定义的类,而不必担心%%pxlocal magic、使用DummyMod和伪造名称空间


要以交互方式pickle类,只需执行“importdill”,然后像第一次那样构建类。然后,您应该能够通过任何sane映射发送它或应用异步函数。

非常感谢!当地的伎俩似乎奏效了。我还找到了一种处理类定义的方法。我将在几分钟内把它推向要点。这是我从
\uuuu main\uuuu
模块中酸洗classdef的实验:你想让我为这个家伙打开一个问题吗?问题在这里:,我现在将尝试快速创建一个潜在的修复原型。
%%pxlocal

class MyClass(object):
    # etc