为什么 python pickle 加载和转储会膨胀磁盘上对象的大小



我在一个名为 b1.pkl 的文件中有一个腌制的对象:

$ ls -l b*
-rw-r--r--  1 fireball  staff  64743950 Oct 11 15:32 b1.pkl

然后我运行以下 python 代码来加载对象并将其转储到新文件中:

import numpy as np
import cPickle as pkl
fin = open('b1.pkl', 'r')
fout = open('b2.pkl', 'w')
x = pkl.load(fin)
pkl.dump(x, fout)
fin.close()
fout.close()

此代码创建的文件是其两倍多:

$ ls -l b*
-rw-r--r--  1 fireball  staff   64743950 Oct 11 15:32 b1.pkl
-rw-r--r--  1 fireball  staff  191763914 Oct 11 15:47 b2.pkl

谁能解释为什么新文件比原始文件大得多?它应该包含完全相同的结构。

可能是最初的泡菜使用了其他协议。例如,尝试将 protocol=2 指定为第二个pickle.dump的关键字参数,然后再次对其进行测试。二元泡菜的尺寸应该小得多。

很可能

您的原始b1.pkl是使用更有效的协议模式(1或2)挑选出来的。因此,您的文件开始时较小。

当您使用 cPickle 加载时,它会自动从文件中为您检测协议。但是当你使用默认参数再次将其转储出来时,它将使用更大的协议 0。这样做是为了可移植性/兼容性。您需要显式请求二进制协议。

import numpy as np
import cPickle
# random data
s = {}
for i in xrange(5000):
    s[i] = np.random.randn(5,5)
# pickle it out the first time with binary protocol
with open('data.pkl', 'wb') as f:
    cPickle.dump(s, f, 2)
# read it back in and pickle it out with default args
with open('data.pkl', 'rb') as f:
    with open('data2.pkl', 'wb') as o:
        s = cPickle.load(f)
        cPickle.dump(s, o)
$ ls -l
1174109 Oct 11 16:05 data.pkl
3243157 Oct 11 16:08 data2.pkl

pkl.dump(x, fout, 2) 可能会导致相同的文件大小。不指定协议版本将使 pickle 使用旧版本 0。

最新更新