问题描述
为避免在开发过程中重复访问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
酸洗是正确的做法吗?我可以使它工作吗?有更好的方法吗?
由于您当前收到的错误消息试图告诉您,您正在尝试腌制不可腌制的实例(在您现在使用的古老的传统腌制协议中),因为它们的类定义了__slots__
而不是__getstate__
方法.
但是,即使更改其类也无济于事,因为那样您会遇到 other 问题-您已经正确地将其识别为可能是由于动态生成的类而引起的.所有pickle
协议都按名称"对类(和函数)进行序列化,从本质上将它们限制为模块中的顶级名称.而且,绝对地序列化一个实例是否需要序列化该类(如果该类不在周围,您以后怎么可能重新构造该实例呢?
因此,您需要以其他方式保存和重新加载数据,从而打破当前对suds.sudsobject
中具体类的直接依赖,转而依赖于可以实际上在访问SOAP服务器时,可以通过此类具体类来实现,或者在从文件中加载数据时,可以通过更简单的自制"类来实现. (毫无疑问,表示实例状态的数据可以表示为dict,因此您可以根据需要将其强制通过pickle,例如通过copy_reg
模块,该模块允许您为被强制对象自定义序列化/反序列化协议来进行非侵入式治疗[[因此您无法随意在类中添加__getstate__
或类似物]] –仅当此类对象之间存在相互引用的丰富网格时,问题才会出现.
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?
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 the copy_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).
这篇关于我如何腌制肥皂水?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!