So far, what I've done is this:
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)
In my main method, this is mainly what I have
#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()
However, this is giving me the following error when the super method is called:
TypeError: must be type, not classobj
How does one overwrite only the two methods, load and dump? The pickle file is under C:\Python27/lib/pickle.py
EDIT The enum.py file can be found here: http://dpaste.com/780897/
Object details: Object is initialized like this:
object = CellSizeRelation(CellSizeRelation.Values.FIRST)
And CellSizeRelation is a class that uses the Enumeration:
class CellSizeRelation(Option):
Values = enum.Enum('FIRST',
'SECOND')
Before I pickle object, I do this:
print object.Values._values
print object.value.enumtype
output
[EnumValue(<enum.Enum object at 0x02E80E50>, 0, 'FIRST'), EnumValue(<enum.Enum object at 0x02E80E50>, 1, 'SECOND')
<enum.Enum object at 0x02E80E50>
After I unpickle and print out the same thing, I get this output:
[EnumValue(<enum.Enum object at 0x02E80E50>, 0, 'FIRST'), EnumValue(<enum.Enum object at 0x02E80E50>, 1, 'SECOND')
<enum.Enum object at 0x02ECF750>
The problem is that the second object address changes; When initialized the first time, the enumtype and _values have the same address. However, after unpickling, they change addresses. This breaks my code when I try to compare two enumValues. If you look in the enumValue class, the compare function tries to do this:
try:
assert self.enumtype == other.enumtype
result = cmp(self.index, other.index)
Because the address changes, the assert function fails. I now somehow need to ensure that the address for the enumtype does not change when unpickled. I was thinking of simply getting the value 'FIRST' from the unpickled file, finding out its index, and reinitializing the object with:
def load:
object = CellSizeRelation(CellSizeRelation.Values[INDEX])
return object
You want to customize the way object state is pickled and unpickled, not customize the load and unload functionality.
You'll have to study the Pickling and unpickling normal class instances chapter, in your case defining a __getstate__ and __setstate__ method should be enough.
What happens in your case is that there is a class-level attribute with EnumValue instances, which are meant to be constants. But on unpickling, new EnumValue instances are created that are not connected to the class-level attribute anymore.
The EnumValue instances do have an index attribute you can use to capture their state as an integer instead of an instance of EnumValue, which we can use to find the correct constant again when reinstating your instances:
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)
So, normally, if there is no __getstate__ the instance __dict__ is pickled. We now do return a copy of that __dict__, but we swapped out the EnumValue instance for it's index (a simple integer). On unpickling, normally the new instance __dict__ is updated with the unpickled __dict__ we captured on pickling, but now that we have a __setstate__ defined, we can swap out the enum index back out for the correct EnumValue again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With