[issue14577] pickling uses __class__ so you can't pickle proxy/mock objects that pretend to be other objects

Michael Foord report at bugs.python.org
Sat Apr 14 13:40:07 CEST 2012


Michael Foord <michael at voidspace.org.uk> added the comment:

test_pickle still passes with only copyreg.py modified. 

With one additional change in pickle.py (line 405 to use type(obj) instead of obj.__class__) the pickling works as I would hope (I would need assistance to fix _pickle):

>>> import sys
[65446 refs]
>>> sys.modules['_pickle'] = None
[65448 refs]
>>> import pickle as p
[70090 refs]
>>> class Foo:    
...  __class__ = property(lambda s: int)
... 
[70140 refs]
>>> p.dumps(Foo())
b'\x80\x03c__main__\nFoo\nq\x00)\x81q\x01.'
[70156 refs]
>>> d = p.dumps(Foo())
[70158 refs]
>>> p.loads(d)
<__main__.Foo object at 0x101410a00>
[70216 refs]
>>> f = p.loads(d)
[70219 refs]
>>> f.__class__
<class 'int'>


However, as you suspect Antoine, it is apparently deliberate that proxies should be pickled as the original:

======================================================================
ERROR: test_newobj_proxies (test.test_pickle.DumpPickle_CLoadPickle)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/compile/py3k-cpython/Lib/test/pickletester.py", line 903, in test_newobj_proxies
    s = self.dumps(p, proto)
  File "/compile/py3k-cpython/Lib/test/test_pickle.py", line 33, in dumps
    p.dump(arg)
  File "/compile/py3k-cpython/Lib/pickle.py", line 235, in dump
    self.save(obj)
  File "/compile/py3k-cpython/Lib/pickle.py", line 342, in save
    self.save_reduce(obj=obj, *rv)
  File "/compile/py3k-cpython/Lib/pickle.py", line 405, in save_reduce
    "args[0] from __newobj__ args has the wrong class")
_pickle.PicklingError: args[0] from __newobj__ args has the wrong class

----------------------------------------------------------------------


Line 891 from pickletester.py: 


    def test_newobj_proxies(self):
        # NEWOBJ should use the __class__ rather than the raw type

I wonder what the use case for that is? If you serialize a proxy object, why would the deserialization code not want a proxy back too?

I guess I can look at implementing copyreg functions for my objects instead.

----------

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


More information about the Python-bugs-list mailing list