Serialización de Python: ¿por qué pickle?

87

Entendí que el decapado de Python es una forma de 'almacenar' un objeto de Python de una manera que respeta la programación de objetos, diferente de una salida escrita en un archivo txt o DB.

¿Tiene más detalles o referencias sobre los siguientes puntos?

  • ¿Dónde se 'almacenan' los objetos en escabeche?
  • ¿Por qué el decapado preserva la representación del objeto más que, digamos, el almacenamiento en DB?
  • ¿Puedo recuperar objetos en escabeche de una sesión de shell de Python a otra?
  • ¿Tiene ejemplos importantes en los que la serialización es útil?
  • ¿La serialización con pickle implica 'compresión' de datos?

En otras palabras, estoy buscando un documento sobre el decapado: Python.doc explica cómo implementar el encurtido, pero parece no profundizar en los detalles sobre el uso y la necesidad de serialización.

Kiriloff
fuente
Supongo que guardar el estado para una restauración posterior o compartir / copiar un objeto en un tiempo de ejecución de Python diferente.
synthesizerpatel
13
Muchas de sus preguntas son respondidas por el artículo de Wikipedia sobre serialización: en.wikipedia.org/wiki/Serialization
NPE
5
¿está preguntando por qué necesitaría Pickle para la serialización en Python? o más bien, ¿cuál es (el propósito de) la serialización después de todo? .
moooeeeep
Quizás sea bueno mencionar los problemas de seguridad con pickle. Se pueden encontrar ejemplos en los documentos y en numerosas preguntas SO, como esta .
djvg

Respuestas:

99

El decapado es una forma de convertir un objeto de Python (lista, dictado, etc.) en un flujo de caracteres. La idea es que este flujo de caracteres contenga toda la información necesaria para reconstruir el objeto en otro script de Python.

En cuanto a dónde se almacena la información en escabeche, normalmente se haría:

with open('filename', 'wb') as f:
    var = {1 : 'a' , 2 : 'b'}
    pickle.dump(var, f)

Eso almacenaría la versión en escabeche de nuestro vardictado en el archivo 'nombre de archivo'. Luego, en otro script, podría cargar desde este archivo en una variable y el diccionario se volvería a crear:

with open('filename','rb') as f:
    var = pickle.load(f)

Otro uso del decapado es si necesita transmitir este diccionario a través de una red (quizás con sockets o algo así). Primero debe convertirlo en un flujo de caracteres, luego puede enviarlo a través de una conexión de socket.

Además, no hay "compresión" de la que hablar aquí ... es solo una forma de convertir de una representación (en RAM) a otra (en "texto").

About.com tiene una buena introducción al decapado aquí .

Austin1howard
fuente
2
por lo general uno haríawith open('filename') as f: ...
moooeeeep
3
Además, debería hacerlo with open(filename, 'wb') as f: ...o no podría escribir en el archivo.
Tim Pietzcker
¡¡Gracias!! Este sobre la gestión de persistencia de Python es bueno, aquí
kiriloff
1
En general, no es una muy buena idea usarlo picklepara transmitir un diccionario a través de una red (json podría ser mejor aquí). Aunque en raras ocasiones podría ser útil, por ejemplo, multiprocessingmodule.
jfs
@Tim Pietzcker: protocol=0(predeterminado en Python2.x) se puede usar con archivos abiertos en modo texto.
jfs
36

El decapado es absolutamente necesario para la computación distribuida y paralela.

Supongamos que desea hacer una reducción de mapa en paralelo con multiprocessing(o en los nodos del clúster con pyina ), luego debe asegurarse de que la función que desea que se asigne a través de los recursos paralelos funcione. Si no se encurtió, no puede enviarlo a otros recursos en otro proceso, computadora, etc. También vea aquí un buen ejemplo.

Para hacer esto, uso eneldo , que puede serializar casi cualquier cosa en Python. Dill también tiene algunas buenas herramientas para ayudarlo a comprender qué está causando que falle su decapado cuando falla su código.

Y, sí, la gente usa la selección para guardar el estado de un cálculo, o su sesión de ipython , o lo que sea. También puede extender Pickler y UnPickler de pickle para hacer compresión con bz2o gzipsi lo desea.

Mike McKerns
fuente
0

Lo encuentro particularmente útil con clases personalizadas grandes y complejas. En un ejemplo particular en el que estoy pensando, "Reunir" la información (de una base de datos) para crear la clase ya era la mitad de la batalla. Entonces, esa información almacenada en la clase puede ser alterada por el usuario en tiempo de ejecución.

Podría tener otro grupo de tablas en la base de datos y escribir otra función para revisar todo lo almacenado y escribirlo en las nuevas tablas de la base de datos. Luego, necesitaría escribir otra función para poder cargar algo guardado leyendo toda esa información nuevamente.

Alternativamente, puede seleccionar toda la clase tal cual y luego almacenarla en un solo campo en la base de datos. Luego, cuando vaya a volver a cargarlo, se cargará todo de una vez como estaba antes. Esto puede terminar ahorrando mucho tiempo y código al guardar y recuperar clases complicadas.

Pollo Max
fuente
-1

es una especie de serialización. use cPickle es mucho más rápido que pickle.

import pickle
##make Pickle File
with open('pickles/corups.pickle', 'wb') as handle:
    pickle.dump(corpus, handle)

#read pickle file
with open('pickles/corups.pickle', 'rb') as handle:
    corpus = pickle.load(handle)
Paritosh Yadav
fuente