我怎样才能得到泡菜泡沫结果?
为了避免在开发过程中重复访问 SOAP 服务器,我尝试缓存结果,以便可以运行其余代码,而无需每次都查询服务器。
使用下面的代码,当我尝试腌制泡沫结果时,我得到一个 PicklingError: Can't pickle
。我想这是因为类是动态创建的。
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
酸洗是正确的做法吗?我能让它发挥作用吗?有更好的办法吗?
To avoid repeatedly accessing a SOAP server during development, I'm trying to cache the results so I can run the rest of my code without querying the server each time.
With the code below I get a PicklingError: Can't pickle <class suds.sudsobject.AdvertiserSearchResponse at 0x03424060>: it's not found as suds.sudsobject.AdvertiserSearchResponse
when I try to pickle a suds result. I guess this is because the classes are dynamically created.
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()
If I drop the -1
protocol version from pickle.dump(result, file, -1)
, I get a different error:
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled
Is pickling the right thing to do? Can I make it work? Is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于您当前收到的错误消息试图告诉您,您正在尝试腌制不可可腌制的实例(在您现在使用的古老遗留腌制协议中),因为它们的类定义
__slots__
但不是__getstate__
方法。但是,即使更改它们的类也无济于事,因为这样您就会遇到其他问题 - 您已经正确地识别出该问题可能是由于动态生成的类造成的。所有pickle协议都“按名称”序列化类(和函数),本质上将它们限制在其模块中的顶级名称。而且,序列化实例绝对确实需要序列化类(否则如果类不存在,您以后怎么可能重建实例?!)。
因此,您需要以其他方式保存和重新加载数据,打破当前对
suds.sudsobject
中具体类的直接依赖,转而依赖于接口(形式化或仅由 duck 定义)当您实际上访问 SOAP 服务器时,可以通过此类具体类来实现,或者当您从文件加载数据时,可以通过更简单的“自制”类来实现。 (表示实例状态的数据无疑可以表示为字典,因此如果您确实愿意,您可以通过 pickle 强制它,例如通过copy_reg
模块,该模块允许您自定义对象的序列化/反序列化协议你被迫以非侵入性的方式治疗[[所以你不能到处添加__getstate__
或类似的东西到他们的类中]]——只有当存在丰富的相互关系时,问题才会出现此类对象之间的引用)。As the error message you're currently getting is trying to tell you, you're trying to pickle instances that are not picklable (in the ancient legacy pickle protocol you're now using) because their class defines
__slots__
but not a__getstate__
method.However, even altering their class would not help because then you'd run into the other problem -- which you already correctly identified as being likely due to dynamically generated classes. All
pickle
protocols serialize classes (and functions) "by name", essentially constraining them to be at top-level names in their modules. And, serializing an instance absolutely does require serializing the class (how else could you possibly reconstruct the instance later if the class was not around?!).So you'll need to save and reload your data in some other way, breaking your current direct dependence on concrete classes in
suds.sudsobject
in favor of depending on an interface (either formalized or just defined by duck typing) that can be implemented both by such concrete classes when you are in fact accessing the SOAP server, or simpler "homemade" ones when you're loading the data from a file. (The data representing instance state can no doubt be represented as a dict, so you can force it through pickle if you really want, e.g. via thecopy_reg
module which allows you to customize serialize/deserialize protocols for objects that you're forced to treat non-invasively [[so you can't go around adding__getstate__
or the like to their classes]] -- the problem will come only if there's a rich mesh of mutual references among such objects).您正在酸洗类对象本身,而不是类的实例对象。如果重新创建类对象,这将不起作用。但是,只要类对象存在,酸洗该类的实例就可以工作。
You are pickling the class object itself, and not instance objects of the class. This won't work if the class object is recreated. However, pickling instances of the class will work as long as the class object exists.