Estoy tratando de guardar y cargar objetos usando el pickle
módulo.
Primero declaro mis objetos:
>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
Después de eso, abro un archivo llamado 'Fruits.obj' (anteriormente creé un nuevo archivo .txt y cambié el nombre de 'Fruits.obj'):
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
Luego de hacer esto cierro mi sesión y comencé una nueva y pongo la siguiente (tratando de acceder al objeto que se suponía que estaba guardado):
file = open("Fruits.obj",'r')
object_file = pickle.load(file)
Pero tengo este mensaje:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
ValueError: read() from the underlying stream did notreturn bytes
No sé qué hacer porque no entiendo este mensaje. ¿Alguien sabe cómo puedo cargar mi objeto 'banana'? ¡Gracias!
EDITAR: Como algunos de ustedes han sugerido, puse:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
No hubo problema, pero el siguiente que puse fue:
>>> object_file = pickle.load(file)
Y tengo error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError
Respuestas:
En cuanto a su segundo problema:
Una vez que haya leído el contenido del archivo, el puntero del archivo estará al final del archivo; no habrá más datos para leer. Tienes que rebobinar el archivo para que se vuelva a leer desde el principio:
Sin embargo, lo que normalmente desea hacer es utilizar un administrador de contexto para abrir el archivo y leer los datos de él. De esta manera, el archivo se cerrará automáticamente después de que el bloque termine de ejecutarse, lo que también te ayudará a organizar las operaciones de tu archivo en partes significativas.
Finalmente, cPickle es una implementación más rápida del módulo pickle en C. Entonces:
fuente
{"a": 1, "b": 2}
crea un diccionario con las claves"a"
y"b"
en él. Esto se denomina expresión de visualización de diccionario en la documentación en línea. Es solo una de las diferentes formasdict
en que se puede construir un objeto de tipo , que es uno de los varios tipos de datos estándar integrados disponibles en Python.pickle
que se importarácpickle
automáticamente si es posible. docs.python.org/3.1/whatsnew/3.0.html#library-changesLo siguiente funciona para mí:
fuente
class Fruits
definido para quepickle.load()
pueda reconstituir el objeto a partir de los datos que se guardaron en el archivo binario. La mejor práctica para este tipo de cosas es poner laclass Fruits
definición en un archivo .py separado (convirtiéndolo en un módulo personalizado) y luegoimport
ese módulo o elementos de él cuando sea necesario (es decir, ambas sesiones). Por ejemplo, si lo pone en un archivo llamadoMyDataDefs.py
, podría escribirfrom MyDataDefs import Fruits
. Avíseme si esto no está claro y actualizaré mi respuesta en consecuencia.my_data_defs.py
usingfrom my_data_defs import Fruits
.También te olvidas de leerlo como binario.
En tu parte de escritura tienes:
En la parte de lectura tienes:
Así que reemplázalo con:
Y funcionará :)
En cuanto a su segundo error, lo más probable es que no se cierre / sincronice el archivo correctamente.
Prueba este fragmento de código para escribir:
Y esto (sin cambios) para leer:
Una versión más ordenada sería usar la
with
declaración.Para la escritura:
Para leer:
fuente
Siempre abierto en modo binario, en este caso
fuente
No abriste el archivo en modo binario.
Deberia trabajar.
Para su segundo error, lo más probable es que el archivo esté vacío, lo que significa que sin darse cuenta lo vació o utilizó el nombre de archivo incorrecto o algo así.
(Esto es asumiendo que realmente cerró su sesión. Si no es así, es porque no cerró el archivo entre la escritura y la lectura).
Probé tu código y funciona.
fuente
Parece que desea guardar sus instancias de clase en todas las sesiones, y usar
pickle
es una forma decente de hacerlo. Sin embargo, hay un paquete llamadoklepto
que abstrae el almacenamiento de objetos en una interfaz de diccionario, por lo que puede elegir seleccionar objetos y guardarlos en un archivo (como se muestra a continuación), o seleccionar los objetos y guardarlos en una base de datos, o en lugar de use pickle use json, o muchas otras opciones. Lo bueno de estoklepto
es que al abstraerse en una interfaz común, lo hace fácil para que no tenga que recordar los detalles de bajo nivel sobre cómo guardar mediante decapado en un archivo, o de otra manera.Tenga en cuenta que funciona para atributos de clase agregados dinámicamente, lo que pickle no puede hacer ...
Luego reiniciamos ...
Klepto
funciona en python2 y python3.Obtenga el código aquí: https://github.com/uqfoundation
fuente
Puede usar anycache para hacer el trabajo por usted. Suponiendo que tiene una función
myfunc
que crea la instancia:Anycache llama
myfunc
por primera vez y selecciona el resultado en un archivocachedir
utilizando un identificador único (según el nombre de la función y los argumentos) como nombre de archivo. En cualquier ejecución consecutiva, se carga el objeto en escabeche.Si
cachedir
se conserva entre ejecuciones de Python, el objeto en escabeche se toma de la ejecución de Python anterior.Los argumentos de la función también se tienen en cuenta. Una implementación refactorizada funciona de la misma manera:
fuente