使用cPickle通过XML-RPC发送复合数据类型

1 投票
1 回答
1110 浏览
提问于 2025-04-16 16:49

我正在做一个分布式处理的项目。
我需要把我的复合数据类型发送给另一个节点,这样我就可以在那个节点上使用它来填充我的树形视图结构。
在我的“tsk_composite”模块里,有这两个类,
这是我的复合数据节点:

class CTskNode(object):    
    def __init__(self, pData, pParent = None):
        self.mData = pData        
        self.mParent = pParent        
        self.mChildren = []   

这是我发送树结构根节点的主类:

class CTskComposite(object):
...
def getRootNode(self):
        self.getImagePartitions()
        return self.mParent  

def getImagePartitions(self):
    #I use this method to create my parentRoot with recursive function
    #it works good

我用这段代码通过cPickle发送我的复合数据:

def _composite(self, pArgs):
    self.mComposite = CTskComposite(pArgs)
    self.mCompositeRootNode = self.mComposite.getRootNode()
    return cPickle.dumps(self.mCompositeRootNode) 

当我在第二个节点接收到复合数据时,它给出了这个错误信息:

ImportError: No module named tsk_composite

当我在第二个节点创建一个名为“tsk_composite”的空模块时,它又给出了这个错误:

AttributeError: 'module' object has no attribute 'CTskNode'

但当我在第二个节点的模块里只写了这一行代码时,它就能完美工作。

class CTskNode(object):pass

其实我并不需要这个模块和类,我该如何通过cpickle只导入模块和类名到另一个节点呢?

1 个回答

4

当 Pickle 处理一个对象时,它会把这个对象的属性名称和属性值,还有类名(包括模块路径)存成一个字典,而不是把方法的定义保存下来。

在反序列化的时候,它会用相同的类重新创建一个对象,并把之前保存的属性设置到这个新对象上。

为了重新创建这个对象,Pickle 会尝试在客户端导入这个类,如果找不到,就会出现你看到的那个错误。

为了避免这个问题,我看到有两个解决办法:

  • 你需要把源代码提供给你的客户端模块,这样在反序列化对象的时候,它就能找到这些源代码。
  • 你可以创建一个虚拟模块(路径、类名和属性都要一样),这样做的前提是这些对象只需要处理属性。

撰写回答