2013-08-27 16 views
13

Daha sonra kullanmak üzere serileştirmem gereken çoklu kullanıcı tanımlı sınıflar içeren büyük nesneler oluşturan kod çalıştırıyorum. Anlatabildiğim kadarıyla, sadece dekapaj, gereksinimlerim için yeterince çok yönlü. Ben onları depolamak için cPickle kullanıyorum ama ürettiği nesneler, 500 mb bellekte çalışan koddan yaklaşık 40 G boyuttadır. Serileştirme hızı bir sorun değildir, ancak nesnenin boyutu. Turşu daha küçük yapmak için kullanabileceğim herhangi bir ipucu veya alternatif süreç var mı?cPickle nesnelerinin boyutunu azaltma

import cPickle 
import gzip 

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

Ve sıkıştırılmış salamura nesneyi yeniden yüklemek için:

+0

Hangi pikle protokolünü kullanıyorsunuz? – user2357112

+0

Protokol sürümü 0. 2 önemli bir fark yaratır mı? – ddn

+0

Bazı fark yaratmalı. Ama ne kadar emin değilim. – user2357112

cevap

26

Sizin için çalışıyor, her zaman turşu bzip2 aracılığıyla boru. Tek sorun bzip2gzip daha hızlı olmalı ... biraz slowish olduğunu, ancak dosya boyutu daha büyük neredeyse 2x geçerli:

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 

yüzden bzip2 dosya boyutu neredeyse 40x daha küçük olduğunu görüyoruz, gzip, 20x daha küçüktür. Ve gzip, ham cPickle performansına oldukça yakındır, görebildiğiniz gibi:

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

Çok iyi bir algoritma olduğunu gördüğüm lzma'yi hesaba katmadın. 200000 rasgele sayıların bir turşu listesini sıkıştırmak için lzma kullandığımda, gzip ve bzip2'yi (en azından önemsiz, hızı kontrol etmemiştim) bastı. –

+0

@Viktor Cpickle'dan daha hızlı bir serileştirme var mı? ("Sizin için başka bir yöntem çalışmıyor" yazıyorsunuz) – DreamFlasher

+0

@DreamFlasher msgpack, json gibi başka daha basit serileştirme modülleri vardır ... Ancak, karmaşık python nesnelerini, yalnızca temel türlerini serileştirmezler. –

21

Bir zipfile ile cPickle dump çağrıyı birleştirebilirsiniz size turşu ve serileştirme başka hiçbir yöntem kullanmanız gerekiyorsa

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

Yüklemeyi tamamlamak için load() func ekleyebilir misiniz? – ealeon

+2

@ealeon bir tane ekledi, umarım peşinde olduğunuzu umarız. – jozzas