Pandas与pickle 0.14.1和0.15.2的向后兼容性问题

Mik*_*e D 7 python pickle mongodb pandas

我们使用pandas Dataframe作为我们时间序列数据的主要数据容器.我们将数据帧打包成二进制blob到mongoDB文档中以便存储,以及关于时间序列blob的元数据的键.

当我们从pandas 0.14.1升级到0.15.2时,我们遇到了错误.

创建pandas Dataframe的二进制blob(0.14.1)

import lz4   
import cPickle

bd = lz4.compress(cPickle.dumps(df,cPickle.HIGHEST_PROTOCOL))
Run Code Online (Sandbox Code Playgroud)

错误案例:使用pandas 0.15.2从mongoDB读回

cPickle.loads(lz4.decompress(bd))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-76f7b0b41426> in <module>()
----> 1 cPickle.loads(lz4.decompress(bd))
TypeError: ('_reconstruct: First argument must be a sub-type of ndarray', <built-in function _reconstruct>, (<class 'pandas.core.index.Index'>, (0,), 'b'))
Run Code Online (Sandbox Code Playgroud)

成功案例:使用pandas 0.14.1从mongoDB读回,没有错误.

这看起来类似于从源代码编译的旧堆栈线程Pandas:默认的pickle行为已更改 来自/sf/users/45142891/的有用评论

您看到的错误消息`TypeError:_reconstruct:第一个参数必须是ndarray的子​​类型,因为python默认的unpickler确保被pickle的类层次结构与它重新创建的完全相同.由于系列版本在版本之间发生了变化,因此默认的unpickler不再可能这样做了(这个恕我直言是pickle工作方式的一个错误).无论如何,大熊猫会破坏具有Seri​​es对象的pre-0.13泡菜."

有关变通方法或解决方案的想法吗?

要重新创建错误:

安装在pandas 0.14.1 env:

df = pd.DataFrame(np.random.randn(10,10))
cPickle.dump(df,open("cp0141.p","wb"))
cPickle.load(open('cp0141.p','r')) # no error
Run Code Online (Sandbox Code Playgroud)

在pandas 0.15.2 env中创建错误:

cPickle.load(open('cp0141.p','r'))
TypeError: ('_reconstruct: First argument must be a sub-type of ndarray', <built-in function_reconstruct>, (<class 'pandas.core.index.Int64Index'>, (0,), 'b'))
Run Code Online (Sandbox Code Playgroud)

Jef*_*eff 7

这是明确提到的Index类,现在不再是子类,ndarray而是一个pandas对象,请参见此处.

你只需要用来pd.read_pickle阅读泡菜.