Dave Halter
Dave Halter

Reputation: 16335

Python pickle: Unclear "AttributeError: can't set attribute"

While using pickle.load(...), there's a possibility that AttributeError: can't set attribute is raised. However on a bigger pickle file this error doesn't help at all (because I have no idea what causes it).

Are there any ways to get more information or to debug this? If there are any other advices how to deal with this problem, I would be glad to hear them!


The error originally comes from Jedi's parser branch. The issue is caused by the latest changes in jedi.parser.fast. If you want to see the error, you need to run python test/run.py on_import 100 twice.


Edit - Cause:

>>> X.y = 3
>>> class X():
...  @property
...  def y(self): pass
... 
>>> X().y = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

The cause is this AttributeError that gives you no information. Combine that with an inheritance of __slots__ and properties in the inherited object + pickle and you get this unclear error.

I still think that it's pickle's fault. I'm going to leave this question open, because I still haven't found a way to debug it properly. Pickle should take that AttributeError and modify it.

Upvotes: 2

Views: 1778

Answers (1)

Mike McKerns
Mike McKerns

Reputation: 35247

dill has pickle debugging tools in dill.detect. I can't see what object you'd like to debug as your code above is not due to pickle… but I can show an example below, regardless.

>>> class Test(object):
...   def __init__(self, x, y):
...     self.x = x
...     self.y = y
... 
>>> x = (i for i in range(10))
>>> y = iter(range(10))
>>> 
>>> t = Test(x,y)
>>> 
>>> import dill
>>> dill.detect.errors(t)
PicklingError("Can't pickle <type 'listiterator'>: it's not found as __builtin__.listiterator",)
>>> dill.detect.badobjects(t) 
<__main__.Test object at 0x1086970d0>
>>> dill.detect.badobjects(t, 1)
{'__hash__': <method-wrapper '__hash__' of Test object at 0x1086970d0>, '__setattr__': <method-wrapper '__setattr__' of Test object at 0x1086970d0>, '__reduce_ex__': <built-in method __reduce_ex__ of Test object at 0x1086970d0>, 'y': <listiterator object at 0x108890d50>, '__reduce__': <built-in method __reduce__ of Test object at 0x1086970d0>, '__str__': <method-wrapper '__str__' of Test object at 0x1086970d0>, '__format__': <built-in method __format__ of Test object at 0x1086970d0>, '__getattribute__': <method-wrapper '__getattribute__' of Test object at 0x1086970d0>, '__delattr__': <method-wrapper '__delattr__' of Test object at 0x1086970d0>, '__repr__': <method-wrapper '__repr__' of Test object at 0x1086970d0>, '__dict__': {'y': <listiterator object at 0x108890d50>, 'x': <generator object <genexpr> at 0x108671f50>}, 'x': <generator object <genexpr> at 0x108671f50>, '__sizeof__': <built-in method __sizeof__ of Test object at 0x1086970d0>, '__init__': <bound method Test.__init__ of <__main__.Test object at 0x1086970d0>>}
>>> dill.detect.trace(True)
>>> dill.dumps(t)
T2: <class '__main__.Test'>
F2: <function _create_type at 0x10945c410>
T1: <type 'type'>
F2: <function _load_type at 0x10945c398>
T1: <type 'object'>
D2: <dict object at 0x10948b7f8>
F1: <function __init__ at 0x108894938>
F2: <function _create_function at 0x10945c488>
Co: <code object __init__ at 0x108873830, file "<stdin>", line 2>
F2: <function _unmarshal at 0x10945c320>
D1: <dict object at 0x1085b9168>
D2: <dict object at 0x10947e910>
D2: <dict object at 0x108898910>
T4: <type 'listiterator'>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
#...snip...
pickle.PicklingError: Can't pickle <type 'listiterator'>: it's not found as __builtin__.listiterator
>>>

I couldn't think of a case where there's an AssertionError from a pickle.dump off the top of my head... but the above debugging tools should work exactly the same way in that case.

If you post a simple reproducible object (i.e. standard lib preferably) that produces an AttributeError on pickling, I'll update my example.

Upvotes: 1

Related Questions