2012-10-11 14 views
6

Ho un oggetto in salamoia in un file chiamato b1.pkl:Perché il pickle python carica e scarica la dimensione di un oggetto sul disco?

$ ls -l b* 
-rw-r--r-- 1 fireball staff 64743950 Oct 11 15:32 b1.pkl 

Poi ho eseguito il seguente codice Python per caricare l'oggetto e discarica in un nuovo file:

import numpy as np 
import cPickle as pkl 

fin = open('b1.pkl', 'r') 
fout = open('b2.pkl', 'w') 

x = pkl.load(fin) 
pkl.dump(x, fout) 

fin.close() 
fout.close() 

Il file questo codice crea è più di due volte più grande:

$ ls -l b* 
-rw-r--r-- 1 fireball staff 64743950 Oct 11 15:32 b1.pkl 
-rw-r--r-- 1 fireball staff 191763914 Oct 11 15:47 b2.pkl 

qualcuno può spiegare il motivo per cui il nuovo file è molto più grande di quella originale? Dovrebbe contenere esattamente la stessa struttura.

+3

è stato il sottaceto originale ottimizzato utilizzando lo stesso protocollo? – root

risposta

10

È possibile che il sottaceto originale abbia utilizzato un altro protocollo. Ad esempio, prova a specificare protocol=2 come argomento della parola chiave sul secondo pickle.dump e testarlo di nuovo. Il sottaceto binario dovrebbe essere di dimensioni molto più ridotte.

+0

Ho provato a specificare il protocollo = 2 e, presto, il file risultante ha le stesse dimensioni dell'originale! – user1389890

+0

quindi è buono :) – root

3

pkl.dump (x, fout, 2) genererebbe probabilmente lo stesso file. Se non si specifica la versione del protocollo, il pickle utilizzerà la vecchia versione 0.

4

Molto probabilmente lo b1.pkl originale è stato decapitato utilizzando la modalità di protocollo più efficiente (1 o 2). Quindi il tuo file inizia più piccolo.

Quando si carica con cPickle, rileverà automaticamente il protocollo dal file. Ma quando vai a scaricarlo di nuovo con argomenti di default, userà il protocollo 0 che è molto più grande. Lo fa per portabilità/compatibilità. È richiesto di richiedere esplicitamente il protocollo binario.

import numpy as np 
import cPickle 

# random data 
s = {} 
for i in xrange(5000): 
    s[i] = np.random.randn(5,5) 

# pickle it out the first time with binary protocol 
with open('data.pkl', 'wb') as f: 
    cPickle.dump(s, f, 2) 

# read it back in and pickle it out with default args 
with open('data.pkl', 'rb') as f: 
    with open('data2.pkl', 'wb') as o: 
     s = cPickle.load(f) 
     cPickle.dump(s, o) 

$ ls -l 
1174109 Oct 11 16:05 data.pkl 
3243157 Oct 11 16:08 data2.pkl 
+0

Quando ho scaricato l'originale, ho usato un parametro pickle di -1. Apparentemente, ha provocato una rappresentazione più compatta sul disco. Immagino che debba aver causato a python l'uso di protocol = 2. – user1389890