1. 程式人生 > >pickle在新舊版本python中的問題

pickle在新舊版本python中的問題

在執行github上deep-siamese-text-similarity 的程式碼時, 遇到args[0] from __newobj__ args has the wrong class 的錯誤, 在一個issue裡找到了解決方法, 但是不知道為什麼, 遂做了一點小實驗做個驗證. 在此記錄.

python2.7

Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
class A(): ... def __init__(): ... self.a = 5 ... >>> a = A() >>> a.a 5 >>> class B(A): ... def __init__(self): ... self.b = 6 ... >>> b = B() >>> b.b 6 >>> b.a Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: B instance has no attribute 'a'
>>> class C(A): ... def __init__(self): ... sup = super(C, self) ... sup.__init__() ... self.c = 7 ... >>> c = C() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __init__ TypeError: super() argument 1 must be type, not
classobj >>> # tips: `super` function can't be applied on old class >>> class A_n(object): ... def __init__(self): ... self.a = 8 ... >>> class C(A_n): ... def __init__(self): ... sup = super(C, self) ... sup.__init__() ... self.c = 9 ... >>> c = C() >>> c.a 8 >>> c.c 9 >>> class D(A_n): ... def __init__(self): ... self.sup = super(D, self) ... self.sup.__init__() ... self.d = 10 ... >>> d = D() >>> d.a 8 >>> d.d 10 >>> import pickle >>> pickle.dumps(c) "ccopy_reg\n_reconstructor\np0\n(c__main__\nC\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'a'\np6\nI8\nsS'c'\np7\nI9\nsb." >>> pickle.dumps(d) "ccopy_reg\n_reconstructor\np0\n(c__main__\nD\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'a'\np6\nI8\nsS'd'\np7\nI10\nsS'sup'\np8\ng0\n(g1\ng2\nNtp9\nRp10\ng5\nbsb." >>>

python3.x

Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: class A():
   ...: def __init__(self):
   ...: self.a = 5
   ...:         

In [2]: class B(A):
   ...: def __init__(self):
   ...: sup = super(B, self)
   ...: sup.__init__()
   ...: self.b = 6
   ...:         

In [3]: a = A()

In [4]: a.a
Out[4]: 5

In [5]: b = B()

In [6]: b.a
Out[6]: 5

In [7]: class C(A):
   ...: def __init__(self):
   ...: self.sup = super(C, self)
   ...: self.sup.__init__()
   ...: self.c = 7
   ...:         

In [8]: c = C()

In [9]: c.a
Out[9]: 5

In [10]: import pickle

In [11]: pickle.dumps(b)
Out[11]: b'\x80\x03c__main__\nB\nq\x00)\x81q\x01}q\x02(X\x01\x00\x00\x00aq\x03K\x05X\x01\x00\x00\x00bq\x04K\x06ub.'

In [12]: pickle.dumps(c)
---------------------------------------------------------------------------
PicklingError Traceback (most recent call last)
<ipython-input-12-4523793c002f> in <module>()
----> 1 pickle.dumps(c)

PicklingError: args[0] from __newobj__ args has the wrong class

新舊版本的python對比發現, 2.7版本中, 使用pickle序列化包含super物件的例項是沒有問題的, 但是在3.x版本中, 使用pickle序列化包含super物件的例項會報錯.