более эффективный способ засолить строку
-
22-08-2019 - |
Вопрос
Модуль Pickle, похоже, использует escape-символы при травлении;это становится неэффективным, например.на массивах 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)
Решение
Попробуйте использовать более позднюю версию протокола Pickle с параметром протокола для pickle.dumps()
.Значение по умолчанию — 0 и представляет собой текстовый формат ASCII.Те, которые больше 1 (советую использовать Pickle.HIGHEST_PROTOCOL).Форматы протоколов 1 и 2 (и 3, но это для py3k) являются двоичными и должны быть более консервативными по пространству.
Другие советы
Решение:
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
z.dumps()
это уже маринованная строка, т. е. ее можно расконсервировать с помощью Pickle.loads():
>>> z = numpy.zeros(1000, numpy.uint8)
>>> s = z.dumps()
>>> a = pickle.loads(s)
>>> all(a == z)
True
Улучшение ответа 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"))