-
-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pickling class instance in dict fails unless you try pickling the object directly first #540
Comments
Generally this shouldn't be the case. However, after a quick look at your code, I see that a Just as an order of business, can you tell me which version of |
For example, how about the following? (this is also a slightly different case, as it's a class defined in
NOTE: the above also seems to work in a Also, can you show the traceback for your failure and success cases when you turn on pickle tracing (i.e. |
Looks like I'm using slightly older dill and numpy versions than you, but your Versions:
Full traceback:First attempt:D2: <dict object at 0x7fee7f2c4690>
INFO:dill:D2: <dict object at 0x7fee7f2c4690>
T4: <class 'gumbi.arrays.ParameterArray'>
INFO:dill:T4: <class 'gumbi.arrays.ParameterArray'>
# T4
INFO:dill:# T4
T4: <class 'numpy.dtype'>
INFO:dill:T4: <class 'numpy.dtype'>
# T4
INFO:dill:# T4
D2: <dict object at 0x7fee7f2c3f50>
INFO:dill:D2: <dict object at 0x7fee7f2c3f50>
# D2
INFO:dill:# D2
# D2
INFO:dill:# D2
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/usr/local/lib/python3.7/dist-packages/IPython/core/formatters.py in __call__(self, obj)
697 type_pprinters=self.type_printers,
698 deferred_pprinters=self.deferred_printers)
--> 699 printer.pretty(obj)
700 printer.flush()
701 return stream.getvalue()
3 frames
/usr/local/lib/python3.7/dist-packages/gumbi/arrays.py in __repr__(self)
245
246 def __repr__(self):
--> 247 return f'{tuple(self.names)}: {np.asarray(self)}'
248
249 def get(self, name, default=None):
AttributeError: 'ParameterArray' object has no attribute 'names' A diversionNu: ((5,), [('d', '<f8')])
INFO:dill:Nu: ((5,), [('d', '<f8')])
F2: <function _create_array at 0x7fee9b9dc440>
INFO:dill:F2: <function _create_array at 0x7fee9b9dc440>
# F2
INFO:dill:# F2
T4: <class 'gumbi.arrays.ParameterArray'>
INFO:dill:T4: <class 'gumbi.arrays.ParameterArray'>
# T4
INFO:dill:# T4
T4: <class 'numpy.dtype'>
INFO:dill:T4: <class 'numpy.dtype'>
# T4
INFO:dill:# T4
D2: <dict object at 0x7fee7f2c3f50>
INFO:dill:D2: <dict object at 0x7fee7f2c3f50>
# D2
INFO:dill:# D2
D2: <dict object at 0x7fee7f2c3fa0>
INFO:dill:D2: <dict object at 0x7fee7f2c3fa0>
T4: <class 'gumbi.aggregation.Standardizer'>
INFO:dill:T4: <class 'gumbi.aggregation.Standardizer'>
# T4
INFO:dill:# T4
D2: <dict object at 0x7fee7f2c3c80>
INFO:dill:D2: <dict object at 0x7fee7f2c3c80>
# D2
INFO:dill:# D2
D2: <dict object at 0x7fee7f2c3e10>
INFO:dill:D2: <dict object at 0x7fee7f2c3e10>
D2: <dict object at 0x7fee7f2c3f00>
INFO:dill:D2: <dict object at 0x7fee7f2c3f00>
# D2
INFO:dill:# D2
# D2
INFO:dill:# D2
# D2
INFO:dill:# D2
# Nu
INFO:dill:# Nu
('d',): [(0.5,) (0.6,) (0.7,) (0.8,) (0.9,)] Second attempt:D2: <dict object at 0x7fee7f2ac0f0>
INFO:dill:D2: <dict object at 0x7fee7f2ac0f0>
Nu: ((5,), [('d', '<f8')])
INFO:dill:Nu: ((5,), [('d', '<f8')])
F2: <function _create_array at 0x7fee9b9dc440>
INFO:dill:F2: <function _create_array at 0x7fee9b9dc440>
# F2
INFO:dill:# F2
T4: <class 'gumbi.arrays.ParameterArray'>
INFO:dill:T4: <class 'gumbi.arrays.ParameterArray'>
# T4
INFO:dill:# T4
T4: <class 'numpy.dtype'>
INFO:dill:T4: <class 'numpy.dtype'>
# T4
INFO:dill:# T4
D2: <dict object at 0x7fee7f2c3f50>
INFO:dill:D2: <dict object at 0x7fee7f2c3f50>
# D2
INFO:dill:# D2
D2: <dict object at 0x7fee7f2c3fa0>
INFO:dill:D2: <dict object at 0x7fee7f2c3fa0>
T4: <class 'gumbi.aggregation.Standardizer'>
INFO:dill:T4: <class 'gumbi.aggregation.Standardizer'>
# T4
INFO:dill:# T4
D2: <dict object at 0x7fee7f2c3c80>
INFO:dill:D2: <dict object at 0x7fee7f2c3c80>
# D2
INFO:dill:# D2
D2: <dict object at 0x7fee7f2c3e10>
INFO:dill:D2: <dict object at 0x7fee7f2c3e10>
D2: <dict object at 0x7fee7f2c3f00>
INFO:dill:D2: <dict object at 0x7fee7f2c3f00>
# D2
INFO:dill:# D2
# D2
INFO:dill:# D2
# D2
INFO:dill:# D2
# Nu
INFO:dill:# Nu
# D2
INFO:dill:# D2
('d',): [(0.5,) (0.6,) (0.7,) (0.8,) (0.9,)] |
@leogama: (unrelated to the rest of the issue) I noticed in the above traceback that there are duplicate entries within the pickle logging trace. Have you seen this behavior before? I haven't seen it previously. |
@JohnGoertz: you can see from the traceback that there's a key difference in the pickling trace in the first attempt, and afterward. The 'correct' trace identities a
while the 'incorrect' trace misses the same identification, and just goes directly to the
So, I am going to assume this is a bug in identifying subclasses of |
This happens when multiple |
1. Propagation can create duplicate messages if the root logger has stdout/stderr handlers set (as observed in uqfoundation#540). 2. `StreamHandler()` uses the `sys.stderr` value as of the time of handler creation, `_StderrHandler()` always use the current value of `sys.stderr`.
I see, interesting. It makes sense that it could fail that way, I think the weirder thing is that the "diversion" fixes it downstream! |
That's probably because, currently, the custom save functions for This explains why, only after you call |
1. Propagation can create duplicate messages if the root logger has stdout/stderr handlers set (as observed in #540). 2. `StreamHandler()` uses the `sys.stderr` value as of the time of handler creation, `_StderrHandler()` always use the current value of `sys.stderr`.
@JohnGoertz: Try your code after updating to master (with the latest commit: bf0f4fa), which should now trigger the registering of the
|
That seems to have done the trick! It now pickles the object correctly within the dictionary on the first try! I should also note that prior to this commit, the same issue arose when the object was contained in a list, but that is fixed now too. !pip install git+https://github.com/uqfoundation/dill.git@bf0f4fa48358fac0a9246a3f12575767d1d14b6f
!pip install gumbi import dill
import numpy as np
import gumbi as gmb
print('dill: ', dill.__version__)
print('numpy: ', np.__version__)
print('gumbi: ', gmb.__version__)
dill.detect.trace(True)
# dill: 0.3.6.dev0
# numpy: 1.21.6
# gumbi: 0.1.11 stdzr = gmb.Standardizer(d={'μ': -0.307, 'σ': 0.158}, log_vars=['d'])
pa = gmb.parray(d=np.arange(5,10)/10, stdzr=stdzr)
pa
with open('test.pkl', 'wb') as f:
dill.dump({'pa': pa}, f)
with open('test.pkl', 'rb') as f:
loaded = dill.load(f)
loaded['pa'] Output:
|
I've found a very bizarre issue where, if I try to pickle an object (with various instance attributes) in a dictionary using dill, it fails on the first attempt. When un-pickling the object, it appears none of the instance attributes have been pickled along with the object. No matter how many times I re-run that cell (in a jupyter notebook), it fails. If I then try to pickle the same object directly, it works, and a subsequent attempt at pickling it in a dictionary now works too.
I've attached reproducible code below, and you can run it in this Colab notebook.
Note, I am the author of gumbi, so please feel free to let me know if this is some issue with gumbi itself!
Imports and setup
First attempt
Saving the object in a dictionary fails, the instance attributes seemingly don't get pickled:
A diversion
Saving the object on its own works:
Second attempt
And now saving the object in a dictionary works:
Note that running the "diversion" before ever running the dictionary pickle works too!
The text was updated successfully, but these errors were encountered: