3.11 pickle -- Serialización de objetos Python

El módulo pickle implementa un algoritmo básico pero potente de ``estibar'' (o serializar, encurtir o aplanar) objetos Python casi arbitrarios. Esto se define como el acto de convertir objetos a una cadena de bytes (y viceversa, ``desestibar''). Es una noción más primitiva que la persistencia, ya que aunque pickle lee y escribe objetos fichero, no gestiona el tema de nombrar los objetos persistentes, ni el (aún más espinoso) tema del acceso concurrente a los objetos persistentes. El módulo pickle puede transformar un objeto complejo en una cadena de bytes y puede transformar la cadena de bytes en un objeto con la misma estructura interna. El destino más evidente de las cadenas de bytes mencionadas es escribirlas a un fichero, pero también se pueden enviar por una red o almacenarlas en una base de datos. El módulo shelve proporciona una interfaz sencialla de estibar y desestibar objetos a ficheros de base de datos tipo DBM.

Nota: El módulo pickle es bastante lento. se dispone de una reimplementación del mismo en C, hasta 1000 veces más rápida, en el módulo cPickle. Tiene la misma interfaz, salvo que Pickler y Unpickler son funciones factoría, no clases (por lo que no se pueden usar como clases base para heredar de ellas).

Aunque el módulo pickle puede utilizar él mismo el módulo interno marshal, se diferencia de éste en el modo en que manipula ciertos tipos de datos:

El formato de datos que utiliza pickle es específico de Python. Este hecho tiene la ventaja de que no hay ninguna restricción impuesta por estándares externos, como XDR (que es incapaz de representar los punteros compartidos). No obstante, también significa que los programas que no sean de Python pueden no ser capaces de reconstruir objetos estibados en Python.

De manera predeterminada, el formato de datos del módulo pickle utiliza una representación ASCII imprimible. Es ligeramente más voluminosa que una representación binaria. La mayor ventaja de utilizar ASCII imprimible (además de otras características de la representación de pickle) es que de cara a depurar o recuperar información es posible para una persona leer el fichero estibado sin más que un simple editor de texto.

Se puede elegir un formato binario, ligeramente más eficiente, especificando un valor verdadero (no cero) en el argumento bin del costructor Pickler o de las funciones dump() and dumps(). El formato binario no es el predeterminado por compatibilidad con el módulo pickle de Python 1.4. En el futuro, el valor predeterminado podría ser el binario.

El módulo pickle no gestiona objetos de código, al contrario que el módulo marshal. Supongo que pickle podría hacerlo y hasta debería, pero no hay una necesidad de ello de momento (siempre que se continúe usando marshal para escribir y leer objetos de código); al menos, esto evita la posibilidad de colar un caballo de Troya en un programa.

A beneficio de los módulos de persistencia escritos utilizando pickle, se soporta el concepto de referencia a un objeto externo al flujo de datos estibado. Tales objetos se referencian mediante un nombre, que es una cadena arbitraria de caracteres ASCII imprimibles. La resolución de dichos nombres no está definida por el módulo pickle, el módulo de objetos persistentes tendrá que implementar un método persistent_load(). Para escribir referencias a objetos persistentes, el módulo persistente debe definir un método persistent_id() que devuelva o None o el identificador persistente de cada objeto.

Hay algunas restricciones en el estibado de instancias de clases.

La primera, la clase debe estar definida en el nivel superior del módulo. Además, todas sus variables de instancia deben ser estibables.

Cuando se desestiba una instancia de clase estibada, no se suele llamara a su método __init__(). Nota: Esto se desvía de las anteriores versiones de este módulo; el cambio se introdujo en Python 1.5b2. El motivo de este cambio es que en muchos casos es conveniente tener un constructor con argumentos; resulta una molestia asumible tener que proporcionar un método __getinitargs__().

Si resulta conveniente que se llame al método __init__() en el desestibado, la clase puede definir un método __getinitargs__(), que ha de devolver una tupla que contenga los argumentos que se han de pasar al constructor de la clase (__init__()). Se invoca este método en tiempo de estibación; la tupla devuelta se incorpora en el formato almacenado de la instancia.

Las clases pueden afinar aún más el modo en que se estiban sus instancias. Si la clase define el método __getstate__(), se llama a éste y el estado devuelto se estiba como contenido de la instancia. Si la clase define el método __setstate__(), se invoca con el estado desestibado (estos métodos se pueden utilizar para implementar la copia de instancias de clase). Si no existe un método __getstate__(), se estiba la el __dict__ de la instancia. Si no existe un método __setstate__(), el objeto estibado ha de ser un diccionario; se asignan sus elementos al diccionario de la nueva instancia (si una clase define tanto __getstate__() como __setstate__(), el objeto de estado no necesita ser un diccionario, sino que los métodos pueden arreglarse como convenga). Este protocolo lo utilizan las operaciones de copia superficial y profunda definidas en el módulo copy.

Hay que destacar que cuando se estiban instancias de clase, no se estiban el código y datos de la clase junto a ellas; sólo los datos de la instancia. Está hecho a propósito, para que se puedan arreglar bugs de una clase y añadirle métodos, y mantener la capacidad de cargar objetos creados con una versión anterior de la clase. Si se planea tener objetos de vida larga que conozcan muchas versiones de una clase, podría traer cuenta poner un número de versión en los objetos para que se puedan hacer las conversiones adecuadas en el método __setstate__() de la clase.

Si se estiba una clase propiamente dicha, sólo se estiba su nombre, no la definición de la clase. Ésta se vuelve a importar en el proceso de desestibado. Por ello, la retricción de que las clases se han de definir al nivel superior del módulo se aplica también a las clases estibadas.

La interfaz se puede resumir así.

Para estibar un objeto x sobre un fichero f, abierto para escritura:

p = pickle.Pickler(f)
p.dump(x)

Un atajo de esto es:

pickle.dump(x, f)

Para desestibar un objeto x desde un fichero f, abierto para lectura:

u = pickle.Unpickler(f)
x = u.load()

Y el atajo correspondiente:

x = pickle.load(f)

La clase Pickler sólo llama al método f.write() con un argumento cadena . Unpickler llama a los métodos f.read() (con un argumento entero) y f.readline() (sin argumentos), devolviendo ambos una cadena. Se permite explícitamente pasar objetos que no sean ficheros aquí, siempre que tengan los métodos mencionados adecuados.

El constructor de la clase Pickler tiene un segundo argumento opcional, bin. Si está presente y es verdadero, se utiliza el formato binario de estibado; en caso contrario se utiliza el formato de estibado a texto (menos eficiente, pero compatible hacia atrás). La clase Unpickler no tiene un argumento para distinguir entre formatos de estibado binarios y de texto, aceptando ambos.

Se pueden estibar los siguientes tipos:

Los intentos de estibar objetos no estibables lanzarán la excepción PicklingError; en tal caso se habrá escrito en el fichero una cantidad indeterminada de caracteres.

Es posible realizar llamadas múltiples al método dump() de la misma instancia de Pickler. Se deben corresponder con el mismo número de llamadas al método load() de la instancia de Unpickler. se estiba el mismo objeto mediante múltiples llamadas a dump(), la carga con load() dará como resultado referencias al mismo objeto. Ojo: éste es un efecto buscado para estibar múltiples objetos sin que intervengan modificaciones en los objetos o sus partes. Si se modifica un objeto y se estiba de nuevo con la misma instancia de Pickler, no se estiba el objeto de nuevo, se estiba una referencia a él y la instancia de Unpickler devolverá el valor antiguo, no el nuevo. Hay dos problemas asociados: (a) detectar cambios y (b) codificar un conjunto mínimo de cambios. No tengo una respuesta válida. La recolección de basura podría también suponer un problema.

Además de las clases Pickler y Unpickler, el módulo define las siguientes funciones y una excepción:

dump (object, file[, bin])
Escribe una representcación del objeto object al fichero abierto file. Equivale a "Pickler(file, bin).dump(object)". Si el argumento opcional bin está presente y no es nulo, se utiliza el formato de estibado binario. Si es cero o se omite, se utiliza el formato de texto (menos eficiente).

load (file)
Lee un objeto estibado del objeto fichero abierto file. Equivale a "Unpickler(file).load()".

dumps (object[, bin])
Devuelve la representación estibada del objeto como cadena, en lugar de escribirla a un fichero. Si el argumento opcional bin está presente y no es nulo, se utiliza el formato de estibado binario. Si es cero o se omite, se utiliza el formato de texto (menos eficiente).

loads (string)
Lee un objeto estibado desde una cadena en lugar de un fichero. Se hace caso omiso de los caracteres posteriores a la representación estibada del objeto

PicklingError
Se lanza esta excepción si se pasa un objeto inestibable a Pickler.dump().

Más informació en:

Module copy_reg:
registro de constructores de la interfaz con pickle.

Module shelve:
bases de datos de objetos con índice; usa pickle.

Module copy:
copia de objetos superficial y profunda.

Module marshal:
serialización de alto rendimiento de tipos internos.


Subsections

Ver Sobre este documento... para obtener información sobre sugerencias.