196 votes

Sauvegarde et chargement d'objets et utilisation de pickle

J'essaie d'enregistrer et de charger des objets à l'aide de pickle module.
Je commence par déclarer mes objets :

>>> class Fruits:pass
...
>>> banana = Fruits()

>>> banana.color = 'yellow'
>>> banana.value = 30

Ensuite, j'ouvre un fichier appelé 'Fruits.obj' (auparavant, j'ai créé un nouveau fichier .txt que j'ai renommé 'Fruits.obj') :

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)

Après avoir fait cela, je ferme ma session et j'en commence une nouvelle et je mets la suivante (en essayant d'accéder à l'objet qui est censé ê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 car je ne comprends pas ce message. Quelqu'un sait-il comment je peux charger mon objet 'banane' ? Je vous remercie de votre attention.

EDITAR: Comme certains d'entre vous l'ont suggéré, j'ai mis :

>>> import pickle
>>> file = open("Fruits.obj",'rb')

Il n'y avait pas de problème, mais le prochain que j'ai mis l'é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

123voto

Jim Brissom Points 10282

Pour ce qui est de 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

Après avoir lu le contenu du fichier, le pointeur de fichier se trouve à la fin du fichier - il n'y a plus de données à lire. Vous devez rembobiner le fichier pour qu'il soit lu à nouveau depuis le début :

file.seek(0)

Ce que vous voulez généralement faire, c'est utiliser un gestionnaire de contexte pour ouvrir le fichier et lire les données qu'il contient. De cette façon, le fichier sera automatiquement fermé après l'exécution du bloc, ce qui vous aidera également à organiser vos opérations sur les fichiers en morceaux significatifs.


Note historique : cPickle est une implémentation plus rapide du module pickle en C qui sera utilisée automatiquement dans python 3.x. Mais dans python 2.x, c'est cPickle les appels explicites nécessaires :

In [1]: import _pickle as 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}

67voto

martineau Points 21665

La méthode suivante 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

50voto

Wolph Points 28062

Vous oubliez aussi de le lire en binaire.

Dans votre partie écrite, 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

Remplacez-la donc par :

file = open("Fruits.obj",'rb')

Et cela fonctionnera :)


Quant à la deuxième erreur, elle est probablement due au fait que le fichier n'a pas été fermé/synchronisé correctement.

Essayez d'écrire ce bout de code :

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()

Et ceci (inchangé) à lire :

>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)

Une version plus soignée consisterait à utiliser la fonction with déclaration.

Pour l'écriture :

>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>>     pickle.dump(banana, fp)

À lire :

>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>>     banana = pickle.load(fp)

17voto

ismail Points 19146

Toujours ouvert en mode binaire, dans ce cas

file = open("Fruits.obj",'rb')

5voto

c0fec0de Points 201

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

Appels d'Anycache myfunc à la première fois et ramène le résultat dans un fichier dans un fichier cachedir en utilisant un identifiant unique (dépendant du nom de la fonction et des arguments) comme nom de fichier. Lors de chaque exécution consécutive, l'objet décapé est chargé.

Si le cachedir est préservé entre les exécutions de Python, l'objet décapé est pris dans l'exécution précédente de Python.

Les arguments de la fonction sont également pris en compte. Une implémentation remanié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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X