![](/img/trans.png)
[英]Python 3: Pickling and UnPickling class instances returning “no persistent load” error
[英]How to overwrite the dump/load methods in the pickle class - customizing pickling and unpickling - Python
到目前為止,我所做的是:
import pickle
class MyPickler(pickle.Pickler):
def __init__(self, file, protocol=None):
super(MyPickler, self).__init__(file, protocol)
class MyUnpickler(pickle.Unpickler):
def __init__(self, file):
super(MyUnpickler, self).__init__(file)
在我的主要方法中,這主要是我所擁有的
#created object, then...
pickledObject = 'testing.pickle'
with open(pickledObject,'wb') as f:
pickle = MyPickler(f)
pickle.dump(object) #object is the object I want to pickle, created before this
with open(pickledObject, 'r') as pickledFile:
unpickle = MyUnpickler(pickledFile)
object2 = unpickle.load()
但是,當調用super方法時,這會給我以下錯誤: TypeError: must be type, not classobj
如何只覆蓋兩種方法,加載和轉儲? pickle文件位於C:\\ Python27 / lib / pickle.py下
編輯 enum.py文件可以在這里找到: http ://dpaste.com/780897/
對象詳細信息:對象初始化如下:
object = CellSizeRelation(CellSizeRelation.Values.FIRST)
CellSizeRelation是一個使用Enumeration的類:
class CellSizeRelation(Option):
Values = enum.Enum('FIRST',
'SECOND')
在我挑選對象之前,我這樣做:
print object.Values._values
print object.value.enumtype
產量
[EnumValue(<enum.Enum object at 0x02E80E50>, 0, 'FIRST'), EnumValue(<enum.Enum object at 0x02E80E50>, 1, 'SECOND')
<enum.Enum object at 0x02E80E50>
在我解開並打印出相同的東西之后,我得到了這個輸出 :
[EnumValue(<enum.Enum object at 0x02E80E50>, 0, 'FIRST'), EnumValue(<enum.Enum object at 0x02E80E50>, 1, 'SECOND')
<enum.Enum object at 0x02ECF750>
問題是第二個對象地址發生了變化; 第一次初始化時, enumtype
和_values
具有相同的地址。 但是,在拆除后,它們會更改地址。 當我嘗試比較兩個enumValues時,這會破壞我的代碼。 如果你查看enumValue
類,compare函數會嘗試這樣做:
try:
assert self.enumtype == other.enumtype
result = cmp(self.index, other.index)
由於地址更改,因此斷言功能失敗。 我現在以某種方式需要確保enumtype的地址在unpickled時不會改變。 我想只是從unpickled文件中獲取值'FIRST',找到它的索引,並使用以下命令重新初始化對象:
def load:
object = CellSizeRelation(CellSizeRelation.Values[INDEX])
return object
您希望自定義對象狀態被pickle和unpickled的方式,而不是自定義加載和卸載功能。
您將不得不研究__getstate__
和unpickling普通類實例章節 ,在您的情況下定義__getstate__
和__setstate__
方法應該足夠了。
在你的情況下發生的是,有一個帶有EnumValue
實例的類級屬性,它們是常量。 但是在unpickling上,創建了新的EnumValue
實例,它們不再連接到類級屬性。
EnumValue
實例確實有一個index
屬性可用於將其狀態捕獲為整數而不是EnumValue
實例,我們可以在恢復實例時再次使用它來查找正確的常量:
class CellSizeRelation(Option):
# skipping your enum definition and __init__ here
def __getstate__(self):
# capture what is normally pickled
state = self.__dict__.copy()
# replace the `value` key (now an EnumValue instance), with it's index:
state['value'] = state['value'].index
# what we return here will be stored in the pickle
return state
def __setstate__(self, newstate):
# re-create the EnumState instance based on the stored index
newstate['value'] = self.Values[newstate['value']]
# re-instate our __dict__ state from the pickled state
self.__dict__.update(newstate)
所以,通常,如果沒有__getstate__
則實例__dict__
被腌制。 我們現在確實返回了__dict__
的副本,但是我們為它的索引(一個簡單的整數)換掉了EnumValue
實例。 在unpickling上,通常新的實例__dict__
會使用我們在pickle上捕獲的unpickled __dict__
更新,但是現在我們已經定義了__setstate__
,我們可以再次將enum索引替換為正確的EnumValue
。
EnumValue
取決於Enum
“枚舉類型”對象之間的id
標識。 這有一些優點和缺點。
主要優點是兩次調用Enum('A', 'B')
定義了不同的枚舉類型。 所以:
osx = Enum('Jaguar', 'Tiger', 'Leopard')
bigcats = Enum('Jaguar', 'Tiger', 'Leopard')
如果您希望能夠將OS X 10.4與條帶化查殺機器區分開來,這可能很有用。
但這也意味着當泡菜bigcats
osx
和bigcats
,它們不僅會彼此不同,它們也將與任何早期的osx
和bigcats
。 一旦你想到它,現在真的有這個。
所以,你的解決方案不能涉及任何類型的黑客泡菜; 它將不得不涉及黑客enum
模塊。
你需要為Enum
定義一個合理的__cmp__
方法, Enum
你有意義。 如果你可以放棄osx-than-bigcats的區別,那很容易。 如果你不能,你需要一些其他的方法(可能在enum
定義中添加一個顯式標記名,或者一個可選但在其他方面隱式自動遞增的計數器?)來處理它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.