2012-10-11 142 views
6

Tengo un objeto estibado en un archivo llamado b1.pkl:¿Por qué python pickle load y dump inflan el tamaño de un objeto en el disco?

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

Luego ejecute el siguiente código Python para cargar el objeto y lo descarga en un archivo nuevo:

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() 

El archivo este código crea es más del doble de 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 

Puede alguien explicar por qué el nuevo archivo es mucho más grande que la original? Debe contener exactamente la misma estructura.

+3

¿Fue la salmuera original recibida utilizando el mismo protocolo? – root

Respuesta

10

Podría ser que el pickle original usara algún otro protocolo. Por ejemplo, intente especificar protocol=2 como argumento de palabra clave en el segundo pickle.dump y vuelva a probarlo. La salmuera binaria debe ser mucho más pequeña en tamaño.

+0

He intentado especificar protocol = 2 y, presto, ¡el archivo resultante es del mismo tamaño que el original! – user1389890

+0

entonces es bueno :) – root

3

pkl.dump (x, fout, 2) probablemente daría como resultado el mismo tamaño de archivo. No especificar la versión del protocolo hará que pickle use la versión anterior 0.

4

Lo más probable es que su original b1.pkl se haya extraído usando el modo de protocolo más eficiente (1 o 2). Por lo tanto, su archivo comienza más pequeño.

Cuando carga con cPickle, automáticamente detectará el protocolo del archivo. Pero cuando vaya y lo descargue de nuevo con argumentos predeterminados, usará el protocolo 0, que es mucho más grande. Lo hace por portabilidad/compatibilidad. Debes solicitar explícitamente el protocolo 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

Cuando dejé el original, usé un parámetro de pickle de -1. Aparentemente, resultó en una representación más compacta en el disco. Supongo que debe haber causado que python use protocol = 2. – user1389890

Cuestiones relacionadas