【问题标题】:more efficient way to pickle a string腌制字符串的更有效方法
【发布时间】:2010-10-16 07:09:17
【问题描述】:

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)

【问题讨论】:

  • 您应该在此处为您的帖子添加一个特定问题。
  • 你想序列化一个 Python 字符串还是一个 numpy 字节数组?
  • 应该是 len(cPickle.dumps(z))

标签: python numpy pickle space-efficiency


【解决方案1】:

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

【解决方案2】:

解决方案:

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

【讨论】:

  • 这里有更多关于这个主题的内容:tinyurl.com/3ymhaj5。基本上,如果您要序列化到磁盘,则只需执行 gzip.open() 而不是 open。
  • @slack3r 该链接已失效。
  • 'ascii' 编解码器无法对位置 1 中的字符 u'\xda' 进行编码:序数不在范围内(128)
【解决方案3】:

对 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"))

【讨论】:

  • -1 (1) 不要硬编码协议编号,使用-1HIGHEST_PROTOCOL。 (2) 随后的压缩是附加的,与他的问题无关。 (3)解压无意义时指定compresslevel;解压缩文件可能需要的任何此类信息都将存储在压缩文件的标头中 - 否则,如果您不知道使用的压缩级别,您将如何解压缩文件?
  • (1) 那么 py2 代码不会读取 py3 对象。 (2) 标题说“对 vartec 的回答进行了改进”,它使用了压缩——我认为它使用了较少的内存,但这可能是一种错误的印象......(3) 已修复
【解决方案4】:

z.dumps() 已经是腌制字符串,也就是说,可以使用 pickle.loads() 来取消腌制:

>>> z = numpy.zeros(1000, numpy.uint8)
>>> s = z.dumps()
>>> a = pickle.loads(s)
>>> all(a == z)
True

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    相关资源
    最近更新 更多