более эффективный способ засолки струны - PullRequest
9 голосов
/ 30 марта 2009

Модуль 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» в z.dumps () == False) и («0» в cPickle.dumps (z.dumps ()) == True)

Ответы [ 4 ]

23 голосов
/ 30 марта 2009

Попробуйте использовать более позднюю версию протокола Pickle с параметром протокола pickle.dumps(). По умолчанию 0 и это текстовый формат ASCII. Единицы больше 1 (я предлагаю вам использовать pickle.HIGHEST_PROTOCOL). Форматы протокола 1 и 2 (и 3, но это для py3k) являются двоичными и должны быть более консервативными.

8 голосов
/ 30 марта 2009

Решение:

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
3 голосов
/ 11 мая 2010

z.dumps() - это уже засеченная строка, то есть ее можно распечатать с помощью pickle.loads ():

>>> z = numpy.zeros(1000, numpy.uint8)
>>> s = z.dumps()
>>> a = pickle.loads(s)
>>> all(a == z)
True
1 голос
/ 10 мая 2010

Улучшение ответа 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"))
...