python - que - Guardar y cargar objetos y usar pickle
python 3.6 pickle (7)
En cuanto a su segundo problema:
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
Después de haber leído el contenido del archivo, el puntero al 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:
file.seek(0)
Sin embargo, lo que normalmente quiere hacer es utilizar un administrador de contexto para abrir el archivo y leer datos de él. De esta forma, el archivo se cerrará automáticamente después de que el bloque termine de ejecutarse, lo que también lo ayudará a organizar sus operaciones de archivos en fragmentos significativos.
Finalmente, cPickle es una implementación más rápida del módulo pickle en C. Entonces:
In [1]: import cPickle
In [2]: d = {"a": 1, "b": 2}
In [4]: with open(r"someobject.pickle", "wb") as output_file:
...: cPickle.dump(d, output_file)
...:
# pickle_file will be closed at this point, preventing your from accessing it any further
In [5]: with open(r"someobject.pickle", "rb") as input_file:
...: e = cPickle.load(input_file)
...:
In [7]: print e
------> print(e)
{''a'': 1, ''b'': 2}
Intento guardar y cargar objetos usando el módulo pickle
.
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 ''Fruits.obj''):
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
Después de hacer esto, cierro mi sesión y comienzo una nueva y pongo la siguiente (tratando de acceder al objeto que se supone que debe guardarse):
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 un 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
Lo siguiente funciona para mí:
class Fruits: pass
banana = Fruits()
banana.color = ''yellow''
banana.value = 30
import pickle
filehandler = open("Fruits.obj","wb")
pickle.dump(banana,filehandler)
filehandler.close()
file = open("Fruits.obj",''rb'')
object_file = pickle.load(file)
file.close()
print(object_file.color, object_file.value, sep='', '')
# yellow, 30
No abriste el archivo en modo binario.
open("Fruits.obj",''rb'')
Deberia trabajar.
Para su segundo error, es probable que el archivo esté vacío, lo que significa que lo vació inadvertidamente o utilizó el nombre de archivo incorrecto o algo así.
(Esto supone que realmente cerró su sesión. De lo contrario, es porque no cerró el archivo entre la escritura y la lectura).
Probé tu código, y funciona.
Parece que quieres guardar tus instancias de clase en todas las sesiones, y usar pickle
es una forma decente de hacerlo. Sin embargo, hay un paquete llamado klepto
que abstrae el guardado de objetos a una interfaz de diccionario, por lo que puede elegir recortar objetos y guardarlos en un archivo (como se muestra a continuación), o recortar los objetos y guardarlos en una base de datos, o en su lugar de uso pickle use json, u otras muchas opciones. Lo bueno de klepto
es que al abstraer a una interfaz común, hace que sea más fácil, por lo que no tiene que recordar los detalles de bajo nivel de cómo guardar mediante decapado en un archivo, o de lo contrario.
Tenga en cuenta que funciona para los atributos de clase agregados dinámicamente, que pickle no puede hacer ...
dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive(''fruits.txt'')
>>> class Fruits: pass
...
>>> banana = Fruits()
>>> banana.color = ''yellow''
>>> banana.value = 30
>>>
>>> db[''banana''] = banana
>>> db.dump()
>>>
Entonces reiniciamos ...
dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive(''fruits.txt'')
>>> db.load()
>>>
>>> db[''banana''].color
''yellow''
>>>
Klepto
funciona en python2 y python3.
Obtenga el código aquí: https://github.com/uqfoundation
Puede usar anycache para hacer el trabajo por usted. Suponiendo que tiene una función myfunc
que crea la instancia:
from anycache import anycache
class Fruits:pass
@anycache(cachedir=''/path/to/your/cache'')
def myfunc()
banana = Fruits()
banana.color = ''yellow''
banana.value = 30
return banana
Anycache llama a myfunc
por primera vez y guarda el resultado en un archivo en cachedir
usando un identificador único (dependiendo del nombre de la función y los argumentos) como nombre de archivo. En cualquier ejecución consecutiva, el objeto escabechado se carga.
Si el cachedir
se conserva entre ejecuciones python, el objeto escabechado se toma de la ejecución anterior de python.
Los argumentos de la función también se tienen en cuenta. Una implementación refactorizada funciona de la misma manera:
from anycache import anycache
class Fruits:pass
@anycache(cachedir=''/path/to/your/cache'')
def myfunc(color, value)
fruit = Fruits()
fruit.color = color
fruit.value = value
return fruit
Siempre abierto en modo binario, en este caso
file = open("Fruits.obj",''rb'')
Te olvidas de leerlo también como binario.
En tu parte de escritura tienes:
open(b"Fruits.obj","wb") # Note the wb part (Write Binary)
En la parte de lectura tienes:
file = open("Fruits.obj",''r'') # Note the r part, there should be a b too
Entonces reemplázalo con:
file = open("Fruits.obj",''rb'')
Y funcionará :)
En cuanto a su segundo error, lo más probable es que sea porque no se cierra / sincroniza el archivo correctamente.
Prueba este pedacito de código para escribir:
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()
Y esto (sin cambios) para leer:
>>> import pickle
>>> file = open("Fruits.obj",''rb'')
>>> object_file = pickle.load(file)
Una versión más limpia estaría usando la declaración with
.
Para la escritura:
>>> import pickle
>>> with open(''Fruits.obj'', ''wb'') as fp:
>>> pickle.dump(banana, fp)
Para leer:
>>> import pickle
>>> with open(''Fruits.obj'', ''rb'') as fp:
>>> banana = pickle.load(fp)