J'essaie de sauvegarder et de charger des objets en utilisant le module pickle
.
Je déclare d’abord mes objets:
>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
Après cela, j'ouvre un fichier appelé 'Fruits.obj' (j'avais précédemment créé un nouveau fichier .txt et renommé 'Fruits.obj'):
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
Après cela je ferme ma session et je commence une nouvelle et je mets la suivante (essayant d’accéder à l’objet qu’il doit être sauvegardé):
file = open("Fruits.obj",'r')
object_file = pickle.load(file)
Mais j'ai ce message:
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
Je ne sais pas quoi faire parce que je ne comprends pas ce message ... Est-ce que quelqu'un sait comment je peux charger mon objet "banane"? ... Merci!
EDIT: Comme certains d'entre vous ont succombé, j'ai mis:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
Il n'y avait pas de problème, mais le suivant que j'ai mis était:
>>> object_file = pickle.load(file)
Et j'ai une erreur:
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
En ce qui concerne votre deuxième problème:
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
Une fois que vous avez lu le contenu du fichier, le pointeur de fichier se trouve à la fin du fichier. Il n’y aura plus de données à lire. Vous devez rembobiner le fichier pour qu'il soit lu depuis le début:
file.seek(0)
Cependant, ce que vous voulez généralement faire, c’est d’utiliser un gestionnaire de contexte pour ouvrir le fichier et en lire les données. De cette façon, le fichier sera automatiquement fermé à la fin de l'exécution du bloc, ce qui vous aidera également à organiser vos opérations sur les fichiers en morceaux significatifs.
Enfin, cPickle est une implémentation plus rapide du module pickle en C. Donc:
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}
Ce qui suit fonctionne pour moi:
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
Toujours ouvert en mode binaire, dans ce cas
file = open("Fruits.obj",'rb')
Vous oubliez de le lire aussi en binaire.
Dans votre partie écriture, vous avez:
open(b"Fruits.obj","wb") # Note the wb part (Write Binary)
Dans la partie lecture, vous avez:
file = open("Fruits.obj",'r') # Note the r part, there should be a b too
Alors remplacez-le par:
file = open("Fruits.obj",'rb')
Et ça va marcher :)
Quant à votre deuxième erreur, elle est probablement due à une fermeture/synchronisation du fichier incorrecte.
Essayez ce code pour écrire:
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()
Et cela (inchangé) à lire:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)
Une version plus propre utiliserait l'instruction with
.
Pour écrire:
>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>> pickle.dump(banana, fp)
A lire:
>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>> banana = pickle.load(fp)
Vous n'avez pas ouvert le fichier en mode binaire.
open("Fruits.obj",'rb')
Devrait marcher.
Pour votre deuxième erreur, le fichier est probablement vide, ce qui signifie que vous l'avez vidé par inadvertance ou utilisé un nom de fichier incorrect.
(Cela suppose que vous avez réellement fermé votre session. Sinon, c'est parce que vous n'avez pas fermé le fichier entre l'écriture et la lecture).
J'ai testé votre code et cela fonctionne.
Il semble que vous souhaitiez enregistrer vos instances de classe au cours de sessions, et utiliser pickle
est un moyen décent de le faire. Cependant, il existe un paquetage appelé klepto
qui résume la sauvegarde des objets dans une interface de dictionnaire. Vous pouvez donc choisir de conserver les objets dans un fichier et de les enregistrer dans un fichier (comme indiqué ci-dessous) ou de les conserver dans une base de données. pickle use use json, ou de nombreuses autres options. La bonne chose à propos de klepto
est que, en résumant sur une interface commune, cela facilite les choses, de sorte que vous n'avez pas à vous rappeler les détails de bas niveau sur la façon de sauvegarder via un pickling dans un fichier ou autrement.
Notez que cela fonctionne pour les attributs de classe ajoutés dynamiquement, ce que pickle ne peut pas faire ...
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()
>>>
Puis on recommence…
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
fonctionne sur python2 et python3.
Obtenez le code ici: https://github.com/uqfoundation
Vous pouvez utiliser anycache pour faire le travail à votre place. En supposant que vous ayez une fonction myfunc
qui crée l'instance:
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 appelle myfunc
pour la première fois et transforme le résultat en un fichier Dans cachedir
en utilisant un identificateur unique (en fonction du nom de la fonction et des arguments) sous la forme nom_fichier . Lors de l'exécution consécutive, l'objet décapé est chargé. .
Si la variable cachedir
est préservée entre les exécutions de python, l'objet décapé est extrait de l'exécution précédente de python.
Les arguments de la fonction sont également pris en compte. Une implémentation refactorisée fonctionne de la même manière:
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