[issue1761028] pickle - cannot unpickle circular deps with custom __hash__

Alexandre Vassalotti report at bugs.python.org
Mon May 25 23:14:07 CEST 2009


Alexandre Vassalotti <alexandre at peadrop.com> added the comment:

Checked this out more throughly and I came to the conclusion this cannot
be fixed without a considerable amount of work.

The problem is pickle adds an Node instance stub in the next_nodes set
before its attributes are ready. Since the stub doesn't have any
attribute at the time its added to the set, the __hash__ method fails
with an AttributeError exception.

To fix this, pickle would need to detect cyclic objects with a custom
__hash__ method; and when it would see one, it would need to emit POP
opcodes to revert the parts of the object already pickled. And then,
pickle would have to re-pickle the cyclic object using a special
procedure that would delay the use of __hash__ until all the attributes
of the object are ready to be used.

I do not believe the bug arises frequently enough to justify adding more
tricky code to pickle. So, I will not fix this myself (feel free to
write a patch, however).

Finally, you can workaround the bug using the __getstate__/__setstate__
mechanism as follow:

class Node(object):
  def __init__(self, i):
    self.i = i
    self.next_nodes = set()
  def __cmp__(self, other):
	return cmp(self.i, other.i)
  def __hash__(self):
    return hash(self.i)
  def __getstate__(self):
    next_nodes = self.next_nodes.copy()
    next_nodes.discard(self)
    return {'i': self.i,
            'self_in_next_nodes': self in self.next_nodes,
            'next_nodes': next_nodes}
  def __setstate__(self, state):
    if state.pop('self_in_next_nodes'):
        self.__dict__.update(state)
        state['next_nodes'].add(self)
    else:
        self.__dict__.update(state)

n = Node(12)
n.next_nodes = set([n])

----------
assignee: alexandre.vassalotti -> 
resolution:  -> wont fix
status: open -> pending

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue1761028>
_______________________________________


More information about the Python-bugs-list mailing list