9

pickle 模块在酸洗时似乎使用了字符串转义字符;这变得低效,例如在 numpy 数组上。考虑以下

z = numpy.zeros(1000, numpy.uint8)
len(z.dumps())
len(cPickle.dumps(z.dumps()))

长度分别为 1133 个字符和 4249 个字符。

z.dumps() 显示类似 "\x00\x00" (字符串中的实际零)的内容,但 pickle 似乎正在使用字符串的 repr() 函数,产生 "'\x00\x00'" (零是 ascii 零)。

即 ("0" in z.dumps() == False) 和 ("0" in cPickle.dumps(z.dumps()) == True)

4

4 回答 4

24

尝试使用更高版本的 pickle 协议,其协议参数为pickle.dumps(). 默认值为 0,是 ASCII 文本格式。大于 1 的(我建议你使用 pickle.HIGHEST_PROTOCOL)。协议格式 1 和 2(以及 3,但这是针对 py3k 的)是二进制的,应该更加节省空间。

于 2009-03-30T02:40:30.510 回答
9

解决方案:

import zlib, cPickle

def zdumps(obj):
  return zlib.compress(cPickle.dumps(obj,cPickle.HIGHEST_PROTOCOL),9)

def zloads(zstr):
  return cPickle.loads(zlib.decompress(zstr))  

>>> len(zdumps(z))
128
于 2009-03-30T10:38:05.587 回答
3

z.dumps()已经是腌制的字符串,即,可以使用 pickle.loads() 将其取消腌制:

>>> z = numpy.zeros(1000, numpy.uint8)
>>> s = z.dumps()
>>> a = pickle.loads(s)
>>> all(a == z)
True
于 2010-05-11T07:26:47.573 回答
1

对 vartec 答案的改进,这似乎更节省内存(因为它不会强制将所有内容都转换为字符串):

def pickle(fname, obj):
    import cPickle, gzip
    cPickle.dump(obj=obj, file=gzip.open(fname, "wb", compresslevel=3), protocol=2)

def unpickle(fname):
    import cPickle, gzip
    return cPickle.load(gzip.open(fname, "rb"))
于 2010-05-09T21:46:27.037 回答