2010-01-30 104 views
8

为了避免在开发过程中反复访问SOAP服务器,我试图缓存结果,以便我可以在不查询服务器的情况下运行我的代码的其余部分。我如何泡泡沫结果?

在下面的代码中,当我尝试泡泡沫结果时,我得到一个PicklingError: Can't pickle <class suds.sudsobject.AdvertiserSearchResponse at 0x03424060>: it's not found as suds.sudsobject.AdvertiserSearchResponse。我想这是因为这些类是动态创建的。

import pickle 
from suds.client import Client 

client = Client(...) 
result = client.service.search(...) 

file = open('test_pickle.dat', 'wb') 
pickle.dump(result, file, -1) 
file.close() 

如果我放弃从pickle.dump(result, file, -1)-1协议版本,我得到一个不同的错误:

TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 

是酸洗做正确的事?我可以使它工作吗?有没有更好的办法?

回答

8

由于您目前得到的是想告诉你的错误信息,你要腌那些 picklable(在你现在正在使用的古代遗留下来的泡菜协议)的情况下,因为它们的类定义__slots__但不是__getstate__方法。

然而,即使改变他们的班级也没有帮助,因为那么你会遇到其他问题 - 您已经正确识别出可能是由于动态生成的类。所有pickle协议“按名称”序列化类(和函数),基本上将它们限制在其模块中的顶级名称。并且,序列化一个实例绝对是是否需要序列化类(如果类不在周围,你怎么可能重建实例?)。

因此,您需要以其他方式保存和重新加载数据,从而打破当前对suds.sudsobject中具体类的直接依赖,转而依赖于接口(可以是形式化的或仅由duck typing定义的)当您实际访问SOAP服务器时,由这些具体类实现,或者当您从文件加载数据时,实现更简单的“自制”类。 (表示实例状态的数据无疑可以表示为字典,所以如果您真的想要,可以通过pickle强制执行它,例如通过copy_reg模块,它允许您为必须处理的对象定制序列化/反序列化协议非侵入性地[[所以你不能在他们的类中加入__getstate__或类似的]] - 只有在这些对象之间有相互引用的丰富网格时,问题才会出现)。

+1

有没有办法让一个动态创建的类的定义,以便它可以保存到一个文件,然后用作一个普通的类? – tponthieux 2011-06-14 20:27:08

2

您正在酸洗类对象本身,而不是类的实例对象。如果重新创建类对象,这将不起作用。然而,只要类对象存在,该类的酸洗实例就会工作。

+0

我想我遵循你所说的,但检查,类型(结果)是和结果.__ class__是所以我不试图泡菜实例? – Mat 2010-01-30 13:51:23

+0

从粘贴的代码看来,你似乎正在酸洗一个实例,但是你提到的错误表明你正在酸洗一个类。 – 2010-01-30 15:52:56

+0

好吧,我不会完全坚果然后:)我得到一个不同的错误,如果我放弃最新的协议-1,我会修改问题,包括看看它是否下降了更多的光。 – Mat 2010-01-30 16:02:27