Меньшие строки из pickle.dumps - PullRequest
0 голосов
/ 28 января 2020

Я пытаюсь придумать, как сделать маринованные струны меньше. Строка pickle будет находиться в скрипте и не может быть файлом.

Пример ниже - небольшой словарь, содержание которого я не знаю. Обратите внимание, какая часть строки просто \ x. Строка, которую я пытаюсь сжать, имеет длину 93 878 символов. У меня есть ограничение: ему нужно использовать библиотеки vanilla python. Я попытался с помощью gzip получить строку из этого. Это экономит около 2 тыс. Символов. Было бы неплохо сэкономить намного больше.

Любые предложения по уменьшению размера струны из маринованных или подобных ванильных python пакетов были бы хорошими. (В этом примере символов меньше, чем в маринованной строке, но обычно это не так.)

#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.

1 Ответ

0 голосов
/ 28 января 2020

Одно дешевое решение - отказаться от некоторых данных о маринадах и использовать функцию

>>> import zlib
>>> len(zlib.compress(pickle.dumps(y))
59
tobytes. На моей машине:
>>> y = {k: v.tobytes() for k, v in x.items()}
>>> len(pickle.dumps(x))
298
>>> len(pickle.dumps(y))
114

Стоимость, конечно, заключается в том, что вы не сохраняете dtype здесь, но экономия "int" в вашем маринаде все еще намного дешевле, особенно если у вас одинаковый тип для всех массивы.

Тогда вы можете добиться гораздо большего с zlib:

*1011*

Сжатие x снижается только до 207, что намного менее оптимально.

...