2015-11-06 108 views
2

我試圖unpickle在python3醃製的對象。這適用於python3,但不適用於python2。這個問題可以被再現至pickle協議0實施例的代碼:unpickle從python3 python2 OrderedDict

import pickle 
import collections 

o = collections.OrderedDict([(1,1),(2,2),(3,3),(4,4)]) 
f = open("test.pkl", "wb") 
pickle.dump(o, f, 0) 
f.close() 

這導致以下PKL文件:

python2:

ccollections 
OrderedDict 
p0 
((lp1 
(lp2 
I1 
aI1 
aa(lp3 
I2 
aI2 
aa(lp4 
I3 
aI3 
aa(lp5 
I4 
aI4 
aatp6 
Rp7 

python3:

cUserString 
OrderedDict 
p0 
(tRp1 
L1L 
L1L 
sL2L 
L2L 
sL3L 
L3L 
sL4L 
L4L 
s. 

當我嘗試從python2加載在python3中創建的pickle文件時,我收到以下異常:

Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import pickle 
>>> f = open("test.pkl", "rb") 
>>> p = pickle.load(f) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/pickle.py", line 1378, in load 
    return Unpickler(file).load() 
    File "/usr/lib/python2.7/pickle.py", line 858, in load 
    dispatch[key](self) 
    File "/usr/lib/python2.7/pickle.py", line 1090, in load_global 
    klass = self.find_class(module, name) 
    File "/usr/lib/python2.7/pickle.py", line 1126, in find_class 
    klass = getattr(mod, name) 
AttributeError: 'module' object has no attribute 'OrderedDict 

但是,將pickle文件中的第一行從UserString更改爲集合類可以解決問題。

Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import pickle 
>>> f = open("test.pkl", "rb") 
>>> p = pickle.load(f) 
>>> p 
OrderedDict([(1L, 1L), (2L, 2L), (3L, 3L), (4L, 4L)]) 

這是python3中的一個bug嗎?

+0

AFAIK,你應該只使用完全相同major.minor版本泡菜和unpickle。 Python3的數據類型在Python2中不存在。如果你需要跨越醃菜,你應該串行到通用的格式,如XML或JSON –

+0

這可能是正確的做法。不幸的是,我沒有控制生成pickle文件的代碼。我只需要從它讀取:( –

回答

1

確保你在Python 2這段代碼導入collections工作對我來說:

的Python 3 - 做酸洗:

import pickle 
import collections 

o = collections.OrderedDict([(1,1),(2,2),(3,3),(4,4)]) 
with open('/home/bo/Desktop/test.pkl', 'wb') as f: 
    pickle.dump(o, f, 2) 

Python的2 - 做在unpickle:

import pickle 
import collections 

with open('/home/bo/Desktop/test.pkl', 'rb') as f: 
    o = pickle.load(f) 

當我這樣做,我可以讀o沒有問題:

>>> o 
0: OrderedDict([(1, 1), (2, 2), (3, 3), (4, 4)]) 
+0

不適用於我。我想知道我在做什麼不同。這裏是我的Python版本: Python 2.7.6 Python 3.4.3 –

+0

你嘗試我的確切代碼snippets?你得到的錯誤表明它是一個命名空間問題,而不是一個pickle版本問題。如果你在pickle文件的源文件中從集合中導入了OrderedDict',那麼對目的地執行相同的操作。 – bbayles

+0

是的,我用這個確切的代碼,這裏是:https://gist.github.com/mwasilew/22f78bafc707127b32a9和https://gist.github.com/mwasilew/2220b3c767af4da0e93f。這仍然給出與以前相同的錯誤。 –