2013-08-27 12 views
13

Ich führe Code aus, der große Objekte erstellt, die mehrere benutzerdefinierte Klassen enthalten, die ich dann für die spätere Verwendung serialisieren muss. Von dem, was ich sagen kann, ist nur Beizen vielseitig genug für meine Anforderungen. Ich habe cPickle verwendet, um sie zu speichern, aber die Objekte, die es erzeugt, sind etwa 40G groß, aus Code, der in 500 MB Speicher läuft. Geschwindigkeit der Serialisierung ist kein Problem, aber die Größe des Objekts ist. Gibt es irgendwelche Tipps oder alternative Prozesse, die ich verwenden kann, um die Gurken kleiner zu machen?Verringern der Größe von cPickle-Objekten

+0

Welche Beize Protokoll verwenden Sie? – user2357112

+0

Protokollversion 0. Würde 2 einen wesentlichen Unterschied machen? – ddn

+0

Es sollte etwas ausmachen. Ich bin mir nicht sicher, wie viel. – user2357112

Antwort

26

Wenn Sie Gurke und keine andere Methode der Serialisierung verwenden müssen arbeitet für Sie, Sie können die Essiggurke immer durch bzip2 leiten. Das einzige Problem ist, dass bzip2 ein wenig slowish ist ... gzip schneller sein sollte, aber die Dateigröße ist fast 2-fach größer:

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 

So sehen wir, dass die Dateigröße der bzip2 ist fast 40x kleiner, gzip ist 20x kleiner. Und gzip ist in der Leistung ziemlich nah an der rohen cPickle, wie Sie sehen können:

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

Sie haben lzma nicht berücksichtigt, was ich finde, ist ein sehr guter Algorithmus. Wenn ich lzma benutzte, um eine gebeizte Liste von 200000 Zufallszahlen zu komprimieren, bezifferte es gzip und bzip2 (zumindest größenweise habe ich die Geschwindigkeit nicht überprüft) –

+0

@Viktor Gibt es eine schnellere Serialisierung als cpickle? (Sie schreiben "keine andere Methode funktioniert für Sie") – DreamFlasher

+0

@DreamFlasher Es gibt andere einfachere Serialisierungsmodule wie msgpack, json ... Aber sie serialisieren nicht komplexe Python-Objekte, nur die grundlegenden Typen. –

21

Sie können Ihre cPickle dump Anruf mit einer Zip-Datei kombinieren:

import cPickle 
import gzip 

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

Und ein Reißverschluss eingelegtes Objekt neu laden:

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

können Sie load() func hinzufügen, um es zu vervollständigen? – ealeon

+2

@ealeon hat eine hinzugefügt, hoffe, dass du danach suchst. – jozzas

Verwandte Themen