2013-08-27 9 views
13

Sto eseguendo il codice che crea oggetti di grandi dimensioni, contenenti più classi definite dall'utente, che devo quindi serializzare per un uso successivo. Da quello che posso dire, solo il decapaggio è abbastanza versatile per le mie esigenze. Ho usato cPickle per memorizzarli, ma gli oggetti che genera sono approssimativamente di 40G, dal codice che viene eseguito in 500 mb di memoria. La velocità di serializzazione non è un problema, ma la dimensione dell'oggetto è. Ci sono suggerimenti o processi alternativi che posso usare per rendere i sottaceti più piccoli?Diminuzione della dimensione degli oggetti cPickle

+0

Quale protocollo di sottaceti stai usando? – user2357112

+0

Protocollo versione 0. 2 farebbe una differenza sostanziale? – ddn

+0

Dovrebbe fare qualche differenza. Non sono sicuro di quanto, però. – user2357112

risposta

26

Se è necessario utilizzare salamoia e nessun altro metodo di serializzazione funziona per te, puoi sempre convogliare il sottaceto attraverso bzip2. L'unico problema è che bzip2 è un po 'slowish ... gzip dovrebbe essere più veloce, ma la dimensione del file è quasi 2x più grande:

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 

Così vediamo che la dimensione del file del bzip2 è quasi 40x più piccola, gzip è 20 volte più piccolo. E gzip è abbastanza vicino alle prestazioni per il raw cPickle, come puoi vedere:

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 
+3

Non hai preso in considerazione lzma, che trovo sia un ottimo algoritmo. Quando ho usato lzma per comprimere una lista decapata di 200000 numeri casuali, ha battuto gzip e bzip2 (almeno al sice, non ho controllato la velocità) –

+0

@Viktor C'è una serializzazione più veloce di cpickle? (Scrivi "nessun altro metodo funziona per te") – DreamFlasher

+0

@DreamFlasher Esistono altri moduli di serializzazione più semplici come msgpack, json ... Ma non serializzano complessi oggetti python, solo i tipi di base. –

21

È possibile combinare la chiamata cPickle dump con un file zip:

import cPickle 
import gzip 

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

E per ricaricare un oggetto in salamoia con zip:

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

puoi aggiungere func() per renderlo completo? – ealeon

+2

@ealeon ne ha aggiunto uno, spero che sia quello che cerchi. – jozzas