web-dev-qa-db-fra.com

Enregistrement et chargement d'objets et utilisation de cornichons

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
68
Peterstone

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}
54
Jim Brissom

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
26
martineau

Toujours ouvert en mode binaire, dans ce cas

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

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)
12
Wolph

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.

4
Lennart Regebro

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

2
Mike McKerns

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
0
c0fec0de