来自 pickle.dumps 的较小字符串

Smaller strings from pickle.dumps

我正在想办法让 pickle strings 变小。 pickle 字符串将驻留在脚本中,不能是文件。

下面的例子是一本我不知道内容的小词典。请注意有多少字符串只是 \x。我要压缩的字符串有 93,878 个字符长。我的一个限制是它需要使用 vanilla python 库。我试过使用 gzip 然后从中获取字符串。它节省了大约 2k 个字符。多存点钱就好了。

任何关于使用 pickle 或类似的 vanilla python 包缩小字符串大小的建议都会很棒。 (例子中字符比pickled字符串少,但一般情况下不是这样。)

#Example precomputed data dict.
x = {}
x["T1"] = np.array([[1,2,3,4,5]])
x["T2"] = np.array([[3,4,5,6,7]])
pickle.dumps(x)

# Below is what will end up being used in a script. I would like to use less characters.
pickle_string = b'\x80\x03}q\x00(X\x02\x00\x00\x00T1q\x01cnumpy.core.multiarray\n_reconstruct\nq\x02cnumpy\nndarray\nq\x03K\x00\x85q\x04C\x01bq\x05\x87q\x06Rq\x07(K\x01K\x01K\x05\x86q\x08cnumpy\ndtype\nq\tX\x02\x00\x00\x00i4q\nK\x00K\x01\x87q\x0bRq\x0c(K\x03X\x01\x00\x00\x00<q\rNNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00tq\x0eb\x89C\x14\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00q\x0ftq\x10bX\x02\x00\x00\x00T2q\x11h\x02h\x03K\x00\x85q\x12h\x05\x87q\x13Rq\x14(K\x01K\x01K\x05\x86q\x15h\x0c\x89C\x14\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00q\x16tq\x17bu.'

precomputed_data = pickle.loads(pickle_string)

继续 kabanus 的想法。

import zlib
s = str(zlib.compress(pickle.dumps(parameters)))
s = s.replace("X", "XX") #searched for XX in the string to begin with. 
s = s.replace("\x", "X")

字符数从 93878 减少到 72688。

一个廉价的解决方案是放弃一些 pickle 数据并使用 Numpy 的 tobytes 功能。在我的机器上:

>>> y = {k: v.tobytes() for k, v in x.items()}
>>> len(pickle.dumps(x))
298
>>> len(pickle.dumps(y))
114

成本当然是你不在这里保留 dtype,但是在你的 pickle 中保存 "int" 仍然便宜得多,特别是如果你的所有数组都具有相同的类型。

然后您可以使用 zlib 做得更好:

>>> import zlib
>>> len(zlib.compress(pickle.dumps(y))
59

压缩 x 仅下降到 207,因此更不理想。