Reputation: 1161
I found a lot of threads about this but the problem of all of them is the namespace. My problem have nothing to do with namespace.
A small example:
import cPickle as pickle
from uncertainties import Variable
class value(Variable):
def __init__(self, args, showing=False):
self.show = showing
Variable.__init__(self, args[0], args[1])
val = value((3,1), True)
print val.nominal_value, val.std_dev(), val.show
fobj = file("pickle.file", "w")
pickle.dump(val, fobj)
fobj.close()
fobj = file("pickle.file", "r")
val = pickle.load(fobj)
fobj.close()
print val.nominal_value, val.std_dev(), val.show
The output of this code:
3.0 1.0 True
3.0 1.0
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/usr/lib/python2.7/dist-packages/IPython/utils/py3compat.pyc in execfile(fname, *where)
173 else:
174 filename = fname
--> 175 __builtin__.execfile(filename, *where)
/home/markus/pickle.py in <module>()
19 val = pickle.load(fobj)
20 fobj.close()
---> 21 print val.nominal_value, val.std_dev(), val.show
AttributeError: 'value' object has no attribute 'show'
The namespace is the same at pickling and unpickling. All attributes of uncertainties.Variable
are restored - only my added one "show" is missed.
Upvotes: 5
Views: 7582
Reputation: 1121196
The uncertainties.Variable()
class uses a __slots__
attribute to save memory. As a result, to be pickleable, it must define a __getstate__
method as well (see Why am I getting an error about my class defining __slots__ when trying to pickle an object?).
If you need to add your own additional attributes, you'll have to override that __getstate__
method. Declaring your additional attributes in a __slot__
attribute of your own is probably a good idea too:
from uncertainties import Variable
class value(Variable):
__slots__ = ('show',) # only list *additional* slots
def __init__(self, args, showing=False):
self.show = showing
super(value, self).__init__(args[0], args[1])
def __getstate__(self):
obj_slot_values = {}
for cls in type(self).mro():
obj_slot_values.update((k, getattr(self, k)) for k in getattr(cls, '__slots__', ()))
# Conversion to a usual dictionary:
return obj_slot_values
This new __getstate__
is required because the Variable.__getstate__
method assumes that there will only be one __slots__
attribute, while each class in the MRO may have one instead.
This is really a limitation of the uncertainties
library; I've submitted a pull request that addresses this and would remove the need to override the __getstate__
method in a subclass.
Upvotes: 6