Comment puis-je utiliser des cornichons pour enregistrer un dict?

370

J'ai parcouru les informations fournies par les documents Python , mais je suis toujours un peu confus. Quelqu'un pourrait-il publier un exemple de code qui écrirait un nouveau fichier, puis utiliser pickle pour y vider un dictionnaire?

Chachmu
la source
5
Lisez ceci: doughellmann.com/PyMOTW/pickle et revenez quand vous avez besoin d'une question spécifique
pyfunc
2
-1 Voir les commentaires précédents. Essayez-le. Ensuite, si cela n'a pas fonctionné (ce ne sera pas toujours le cas), une question dirigée peut être formulée (avec une ou deux hypothèses qui peuvent être testées et "interrogées", éventuellement avant de poser la question à d'autres personnes). Par exemple, y avait-il une erreur de syntaxe? Une exception? Les valeurs sont-elles revenues brouillées?
1
J'ai essayé de l'utiliser pour enregistrer des informations de pygame. J'ai utilisé les informations ci-dessus et mon code ressemble à ceci:
Chachmu
name = raw_input ('nom du fichier d'entrée:') tf = open (nom + '. pkl', 'wb') pickle.dump (total, tf) tf.close ()
Chachmu
2
Vous devriez poser une nouvelle question sur la façon de décaper des objets de surface
John La Rooy

Réponses:

728

Essaye ça:

import pickle

a = {'hello': 'world'}

with open('filename.pickle', 'wb') as handle:
    pickle.dump(a, handle, protocol=pickle.HIGHEST_PROTOCOL)

with open('filename.pickle', 'rb') as handle:
    b = pickle.load(handle)

print a == b
Mixeur
la source
4
@houbysoft: Pourquoi avez-vous supprimé pickle.HIGHEST_PROTOCOL?
Blender
37
@Blender: non pertinent et inutilement compliqué pour ce niveau de question - l'utilisateur moyen sera très bien avec les valeurs par défaut.
houbysoft
28
@houbysoft: Vrai pour les utilisateurs de Python 3, mais sur Python 2, l'utilisation du protocole par défaut (0) est non seulement incroyablement inefficace en termes de temps et d'espace, mais il ne peut pas réellement gérer beaucoup de choses que le protocole 2+ gère très bien (par exemple, nouveau classes de style qui utilisent __slots__). Je ne dis pas que vous devriez toujours utiliser HIGHEST_PROTOCOL, mais vous assurer que vous n'utilisez pas le protocole 0 ou 1 est en fait assez important.
ShadowRanger
11
Que fait-il pickle.HIGHEST_PROTOCOLréellement?
BallpointBen
7
@BallpointBen: Il sélectionne la version de protocole la plus élevée prise en charge par votre version de Python: docs.python.org/3/library/pickle.html#data-stream-format
Blender
92
import pickle

your_data = {'foo': 'bar'}

# Store data (serialize)
with open('filename.pickle', 'wb') as handle:
    pickle.dump(your_data, handle, protocol=pickle.HIGHEST_PROTOCOL)

# Load data (deserialize)
with open('filename.pickle', 'rb') as handle:
    unserialized_data = pickle.load(handle)

print(your_data == unserialized_data)

L'avantage HIGHEST_PROTOCOLest que les fichiers deviennent plus petits. Cela rend le décapage parfois beaucoup plus rapide.

Remarque importante : La taille maximale du fichier de cornichon est d'environ 2 Go.

Voie alternative

import mpu
your_data = {'foo': 'bar'}
mpu.io.write('filename.pickle', data)
unserialized_data = mpu.io.read('filename.pickle')

Formats alternatifs

Pour votre application, les éléments suivants peuvent être importants:

  • Prise en charge par d'autres langages de programmation
  • Lecture / écriture
  • Compacité (taille du fichier)

Voir aussi: Comparaison des formats de sérialisation des données

Dans le cas où vous cherchez plutôt un moyen de créer des fichiers de configuration, vous voudrez peut-être lire mon court article Fichiers de configuration en Python

Martin Thoma
la source
1
Je pense que la limite de 2 Go a été supprimée avec le protocole = 4 et plus.
ComputerScientist
28
# Save a dictionary into a pickle file.
import pickle

favorite_color = {"lion": "yellow", "kitty": "red"}  # create a dictionary
pickle.dump(favorite_color, open("save.p", "wb"))  # save it into a file named save.p

# -------------------------------------------------------------
# Load the dictionary back from the pickle file.
import pickle

favorite_color = pickle.load(open("save.p", "rb"))
# favorite_color is now {"lion": "yellow", "kitty": "red"}
user3465692
la source
1
est-il nécessaire d'utiliser un close () après le open ()?
PlsWork
1
Oui, en général. Cependant, dans CPython (le python par défaut que vous avez probablement), le fichier est automatiquement fermé chaque fois que l'objet fichier expire (lorsque rien n'y fait référence). Dans ce cas, puisque rien ne fait référence à l'objet fichier après avoir été renvoyé par open (), il sera fermé dès le retour du chargement. Ceci n'est pas considéré comme une bonne pratique et causera des problèmes sur d'autres systèmes
Ankur S
14

En général, le décapage d'un dictéchouera sauf si vous n'avez que des objets simples, comme des chaînes et des entiers.

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[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 numpy import *
>>> type(globals())     
<type 'dict'>
>>> import pickle
>>> pik = pickle.dumps(globals())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle module objects
>>> 

Même un très simple dictéchouera souvent. Cela dépend simplement du contenu.

>>> d = {'x': lambda x:x}
>>> pik = pickle.dumps(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 748, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <function <lambda> at 0x102178668>: it's not found as __main__.<lambda>

Cependant, si vous utilisez un meilleur sérialiseur comme dillou cloudpickle, la plupart des dictionnaires peuvent être décapés:

>>> import dill
>>> pik = dill.dumps(d)

Ou si vous souhaitez enregistrer votre dictfichier dans un fichier ...

>>> with open('save.pik', 'w') as f:
...   dill.dump(globals(), f)
... 

Ce dernier exemple est identique à toutes les autres bonnes réponses publiées ici (qui, en plus de négliger la picklabilité du contenu du, dictsont bonnes).

Mike McKerns
la source
9
>>> import pickle
>>> with open("/tmp/picklefile", "wb") as f:
...     pickle.dump({}, f)
... 

normalement, il est préférable d'utiliser l'implémentation cPickle

>>> import cPickle as pickle
>>> help(pickle.dump)
Help on built-in function dump in module cPickle:

dump(...)
    dump(obj, file, protocol=0) -- Write an object in pickle format to the given file.

    See the Pickler docstring for the meaning of optional argument proto.
John La Rooy
la source
6

Si vous voulez simplement stocker le dict dans un seul fichier, utilisez picklecomme ça

import pickle

a = {'hello': 'world'}

with open('filename.pickle', 'wb') as handle:
    pickle.dump(a, handle)

with open('filename.pickle', 'rb') as handle:
    b = pickle.load(handle)

Si vous souhaitez enregistrer et restaurer plusieurs dictionnaires dans plusieurs fichiers pour la mise en cache et stocker des données plus complexes, utilisez anycache . Il fait tout le reste dont vous avez besoinpickle

from anycache import anycache

@anycache(cachedir='path/to/files')
def myfunc(hello):
    return {'hello', hello}

Anycache stocke les différents myfuncrésultats en fonction des arguments des différents fichiers cachediret les recharge.

Voir la documentation pour plus de détails.

c0fec0de
la source
6

Un moyen simple de vider une donnée Python (par exemple un dictionnaire) dans un fichier pickle.

import pickle

your_dictionary = {}

pickle.dump(your_dictionary, open('pickle_file_name.p', 'wb'))
Prashanth Muthurajaiah
la source
3
import pickle

dictobj = {'Jack' : 123, 'John' : 456}

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()
Rahul Nair
la source
-8

J'ai trouvé le décapage déroutant (peut-être parce que je suis épais). J'ai trouvé que cela fonctionne, cependant:

myDictionaryString=str(myDictionary)

Que vous pouvez ensuite écrire dans un fichier texte. J'ai renoncé à utiliser des cornichons car je recevais des erreurs me disant d'écrire des entiers dans un fichier .dat. Je m'excuse de ne pas avoir utilisé de cornichons.

Pedro Rhian
la source
1
-1: Devrait l'enregistrer tel quel (c'est-à-dire un objet python) afin que nous puissions le lire plus tard sans heures d'attente pour l'exécuter à nouveau. Pickle nous permet de stocker un objet python à lire plus tard.
Catbuilts
Il s'agit d'une ancienne réponse qui revient dans la file d'attente des messages de faible qualité. Ce n'est pas une mauvaise solution dans la mesure où cela fonctionne probablement pour des dictionnaires très simples, mais il est très raisonnable pour a dictde contenir davantage de profondeur d'objets (qui peuvent être imprimés uniquement par nom) et / ou des objets sans aucune représentation de chaîne complète.
ti7
1
Pour ajouter au point de @ ti7, quel que soit le mérite technique de la réponse, ce message n'est pas VLQ. Si quelqu'un estime que cette réponse est inexacte, il doit voter contre et / ou commenter en expliquant pourquoi, et non la marquer comme VLQ.
EJoshuaS