Author anselm.kruis
Recipients anselm.kruis, rhettinger
Date 2013-05-19.18:41:58
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1368988919.46.0.250713350438.issue18015@psf.upfronthosting.co.za>
In-reply-to
Content
Change 18303391b981 breaks unpickling named tuples pickled by 2.7.3 and 2.7.4.

See closed issue #15535 for the full story. Unfortunately Raymond was wrong, when he wrote that the addition of __dict__ was a 2.7.4 change. It was added by changeset 26d5f022eb1a in 2.7.3.

Now 2.7.5 can't unpickle any named tuples pickled by 2.7.3, which is probably one of the most widely used python versions.


Example:

Pickle a namd tuple using 2.7.3 and unpickle it using 2.7.5.

anselm@Emmy:~$ python2.7
Python 2.7.3 (default, Sep 16 2012, 21:46:37) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import collections
>>> import pickletools
>>> import pickle
>>> N=collections.namedtuple("N","a")
>>> n=N(1)
>>> p=pickle.dumps(n, 2)
>>> p2=pickletools.optimize(p)
>>> pickletools.dis(p2)
    0: \x80 PROTO      2
    2: c    GLOBAL     '__main__ N'
   14: K    BININT1    1
   16: \x85 TUPLE1
   17: \x81 NEWOBJ
   18: c    GLOBAL     'collections OrderedDict'
   43: ]    EMPTY_LIST
   44: ]    EMPTY_LIST
   45: (    MARK
   46: U        SHORT_BINSTRING 'a'
   49: K        BININT1    1
   51: e        APPENDS    (MARK at 45)
   52: a    APPEND
   53: \x85 TUPLE1
   54: R    REDUCE
   55: b    BUILD
   56: .    STOP
highest protocol among opcodes = 2
>>> print repr(p2)
'\x80\x02c__main__\nN\nK\x01\x85\x81ccollections\nOrderedDict\n]](U\x01aK\x01ea\x85Rb.'


anselm@Emmy:~/sc/eclipsews/fg2py$ fg2python
Python 2.7.5 (default, May 18 2013, 17:02:17) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> import collections
>>> N=collections.namedtuple("N","a")
>>> pickle.loads('\x80\x02c__main__\nN\nK\x01\x85\x81ccollections\nOrderedDict\n]](U\x01aK\x01ea\x85Rb.')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/anselm/sc/eclipsews/fg2py/arch/rhel4u4-x86_64/lib/python2.7/pickle.py", line 1419, in loads
    return Unpickler(file).load()
  File "/home/anselm/sc/eclipsews/fg2py/arch/rhel4u4-x86_64/lib/python2.7/pickle.py", line 895, in load
    dispatch[key](self)
  File "/home/anselm/sc/eclipsews/fg2py/arch/rhel4u4-x86_64/lib/python2.7/pickle.py", line 1261, in load_build
    d = inst.__dict__
AttributeError: 'N' object has no attribute '__dict__'


As we can see from the trace back, the problem arises from the pickle op-code 'BUILD'. BUILD requires that the object to be build either has a method __setstate__ or has an attribute __dict__. Therefore I propose:

- Revert change 18303391b981 and add a __getstate__ method
  This is the Python 3 fix for the problem.

or

- Add a method __setstate__:

  def __setstate__(self, state): 
     """For compatibility with Python 2.7.3 and 2.7.4"""
     pass
History
Date User Action Args
2013-05-19 18:41:59anselm.kruissetrecipients: + anselm.kruis, rhettinger
2013-05-19 18:41:59anselm.kruissetmessageid: <1368988919.46.0.250713350438.issue18015@psf.upfronthosting.co.za>
2013-05-19 18:41:59anselm.kruislinkissue18015 messages
2013-05-19 18:41:58anselm.kruiscreate