Уменьшение размера объектов cPickle

Я запускаю код, который создает большие объекты, содержащие несколько пользовательских классов, которые затем я должен сериализовать для последующего использования. Из того, что я могу сказать, только травление достаточно универсально для моих требований. Я использую cPickle для их хранения, но объекты, которые он генерирует, имеют размер приблизительно 40G, от кода, который работает в 500 Мб памяти. Скорость сериализации не является проблемой, но размер объекта. Есть ли какие-либо советы или альтернативные процессы, которые я могу использовать, чтобы уменьшить количество соленья?

Ответ 1

Если вы должны использовать рассол, и никакой другой метод сериализации для вас не работает, вы всегда можете направить рассол через bzip2. Единственная проблема заключается в том, что bzip2 немного медленнее... gzip должен быть быстрее, но размер файла почти вдвое больше:

In [1]: class Test(object):
            def __init__(self):
                self.x = 3841984789317471348934788731984731749374
                self.y = 'kdjsaflkjda;sjfkdjsf;klsdjakfjdafjdskfl;adsjfl;dasjf;ljfdlf'
        l = [Test() for i in range(1000000)]

In [2]: import cPickle as pickle          
        with open('test.pickle', 'wb') as f:
            pickle.dump(l, f)
        !ls -lh test.pickle
-rw-r--r--  1 viktor  staff    88M Aug 27 22:45 test.pickle

In [3]: import bz2
        import cPickle as pickle
        with bz2.BZ2File('test.pbz2', 'w') as f:
            pickle.dump(l, f)
        !ls -lh test.pbz2
-rw-r--r--  1 viktor  staff   2.3M Aug 27 22:47 test.pbz2

In [4]: import gzip
        import cPickle as pickle
        with gzip.GzipFile('test.pgz', 'w') as f:
            pickle.dump(l, f)
        !ls -lh test.pgz
-rw-r--r--  1 viktor  staff   4.8M Aug 27 22:51 test.pgz

Итак, мы видим, что размер файла bzip2 почти в 40 раз меньше, gzip меньше на 20 раз. И gzip довольно близок по производительности к raw cPickle, как вы можете видеть:

cPickle : best of 3: 18.9 s per loop
bzip2   : best of 3: 54.6 s per loop
gzip    : best of 3: 24.4 s per loop

Ответ 2

Вы можете комбинировать вызов cPickle dump с zipfile:

import cPickle
import gzip

def save_zipped_pickle(obj, filename, protocol=-1):
    with gzip.open(filename, 'wb') as f:
        cPickle.dump(obj, f, protocol)

И для повторной загрузки замаскированного маринованного объекта:

def load_zipped_pickle(filename):
    with gzip.open(filename, 'rb') as f:
        loaded_object = cPickle.load(f)
        return loaded_object