Here is code to demonstrate the problem. All asserts
succeed except the last, showing that pickle and
cPickle both handle a "classic" cycle correctly, but
only cPickle handles new-style cycles correctly. It
would appear that the problem is that the pure-Python
pickle isn't putting the object into its 'memo' until
*after* the object's state has been pickled. Thus, the
identity is not preserved on unpickling. This may be
true for other object types that use __reduce__, but I
have not verified this.
import pickle, cPickle
class X: pass
x = X()
x.x = x
x2 = cPickle.loads(cPickle.dumps(x))
assert x2.x is x2
x2 = pickle.loads(pickle.dumps(x))
assert x2.x is x2
class Y(object): pass
y = Y()
y.y = y
y2 = cPickle.loads(cPickle.dumps(y))
assert y2.y is y2
# this fails
y2 = pickle.loads(pickle.dumps(y))
assert y2.y is y2
|