2009-03-30 13 views
9

El módulo de salmuera parece utilizar caracteres de escape de cadena al decapado; esto se vuelve ineficiente, p. en matrices numpy. Tenga en cuenta lo siguientemanera más eficiente de extraer una cadena

z = numpy.zeros(1000, numpy.uint8) 
len(z.dumps()) 
len(cPickle.dumps(z.dumps())) 

Las longitudes son de 1133 caracteres y 4249 caracteres respectivamente.

z.dumps() revela algo así como "\ x00 \ x00" (ceros reales en cadena), pero pickle parece estar utilizando la función repr() de la cadena, produciendo "'\ x00 \ x00'" (siendo ceros ascii ceros).

es decir ("0" en z.dumps() == false) y ("0" en cPickle.dumps (z.dumps()) == true)

+0

Debe agregar una determinada pregunta a su publicación he re. –

+0

¿Qué quiere serializar una cadena de Python o una matriz numerada de bytes? – jfs

+1

debe ser len (cPickle.dumps (z)) – vartec

Respuesta

23

Trate de usar una versión posterior de la protocolo pickle con el parámetro de protocolo a pickle.dumps(). El valor predeterminado es 0 y es un formato de texto ASCII. Unos más de 1 (sugiero que use pickle.HIGHEST_PROTOCOL). Los formatos de protocolo 1 y 2 (y 3, pero eso es para py3k) son binarios y deberían ser más conservadores del espacio.

+0

[Python 3 usa el protocolo 3 de forma predeterminada.] (Https://docs.python.org/3/library/pickle.html#data-stream-format) –

8

Solución:

import zlib, cPickle 

def zdumps(obj): 
    return zlib.compress(cPickle.dumps(obj,cPickle.HIGHEST_PROTOCOL),9) 

def zloads(zstr): 
    return cPickle.loads(zlib.decompress(zstr)) 

>>> len(zdumps(z)) 
128 
+0

Aquí está algo más sobre el tema: http://tinyurl.com/3ymhaj5. Básicamente, si estás serializando en un disco, simplemente puedes hacer gzip.open() en lugar de abrir. –

+0

@ slack3r ese enlace está muerto. – kynan

+0

códec 'ascii' no puede codificar el carácter u '\ xda' en la posición 1: ordinal no en rango (128) –

1

Una mejora de la respuesta de VarTec, que parece un poco más eficiente de la memoria (ya que no obliga a todo en una cadena):

def pickle(fname, obj): 
    import cPickle, gzip 
    cPickle.dump(obj=obj, file=gzip.open(fname, "wb", compresslevel=3), protocol=2) 

def unpickle(fname): 
    import cPickle, gzip 
    return cPickle.load(gzip.open(fname, "rb")) 
+0

-1 (1) No codifica números de protocolo, use '-1' o' HIGHEST_PROTOCOL' . (2) La compresión posterior es un ADD-ON y es irrelevante para su pregunta. (3) Especificar 'compresslevel' cuando se descomprime no tiene sentido; cualquier información que pueda ser necesaria para descomprimir el archivo se almacenará en el encabezado del archivo comprimido; de lo contrario, ¿cómo podría descomprimir un archivo si no supiera qué nivel de compresión se utilizó? –

+0

(1) Entonces el código py2 no leerá objetos py3. (2) el encabezado dice "una mejora de la respuesta de Vartec", que usaba compresión, creo que usaba menos memoria, pero podría haber sido una falsa impresión ... (3) arreglado – gatoatigrado

3

z.dumps() ya está en escabeche cadena, es decir, puede ser deshecha utilizando pickle.loads():

>>> z = numpy.zeros(1000, numpy.uint8) 
>>> s = z.dumps() 
>>> a = pickle.loads(s) 
>>> all(a == z) 
True 
Cuestiones relacionadas