Come posso usare pickle per salvare un dict?


370

Ho esaminato le informazioni che il documenti di Python , ma sono ancora un po 'confuso. Qualcuno potrebbe pubblicare un codice di esempio che scriverebbe un nuovo file e quindi utilizzare pickle per scaricare un dizionario in esso?


5
Leggi questo: doughellmann.com/PyMOTW/pickle e torna quando hai bisogno di una domanda specifica
pyfunc,

2
-1 Vedi i commenti precedenti. Provalo. Quindi, se non ha funzionato (non sempre), è possibile formulare una domanda diretta (insieme a un'ipotesi o due che può essere verificata e "interrogata", possibilmente prima di porre la domanda ad altre persone). Ad esempio c'è stato un errore di sintassi? Un'eccezione? I valori sono tornati confusi?

1
Ho provato a usarlo per salvare informazioni da Pygame. Ho usato le informazioni sopra e il mio codice è simile al seguente:
Chachmu,

name = raw_input ('input file name:') tf = open (name + '. pkl', 'wb') pickle.dump (total, tf) tf.close ()
Chachmu

2
Dovresti porre una nuova domanda su come decapare gli oggetti di superficie
John La Rooy,

Risposte:


728

Prova questo:

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

4
@houbysoft: perché l'hai rimosso pickle.HIGHEST_PROTOCOL?
Blender il

37
@Blender: irrilevante e inutilmente complicato per questo livello di domanda - l'utente medio andrà bene con le impostazioni predefinite.
houbysoft,

28
@houbysoft: True per gli utenti di Python 3, ma su Python 2, l'utilizzo del protocollo predefinito (0) non è solo incredibilmente inefficiente nel tempo e nello spazio, ma in realtà non può gestire molte cose che il protocollo 2+ gestisce bene (es. nuovo in stile che usano __slots__). Non sto dicendo che dovresti sempre usare HIGHEST_PROTOCOL, ma assicurarti di non usare il protocollo 0 o 1 è in realtà piuttosto importante.
ShadowRanger,

11
Cosa fa pickle.HIGHEST_PROTOCOLeffettivamente?
BallpointBen,

7
@BallpointBen: seleziona la versione di protocollo più alta supportata dalla tua versione di 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)

Il vantaggio HIGHEST_PROTOCOLè che i file diventano più piccoli. Questo rende il distacco a volte molto più veloce.

Avviso importante : la dimensione massima del file di pickle è di circa 2 GB.

Modo alternativo

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

Formati alternativi

Per la tua applicazione, potrebbe essere importante quanto segue:

  • Supporto da altri linguaggi di programmazione
  • Performance di lettura / scrittura
  • Compattezza (dimensione del file)

Vedi anche: Confronto dei formati di serializzazione dei dati

Nel caso in cui tu stia cercando un modo per creare file di configurazione, potresti voler leggere il mio breve articolo File di configurazione in Python


1
Penso che il limite di 2 GB sia stato rimosso con protocollo = 4 e versioni successive.
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"}

1
è necessario usare un close () dopo open ()?
PlsWork,

1
Sì, in generale. Tuttavia in CPython (il python predefinito che probabilmente hai) il file viene automaticamente chiuso ogni volta che l'oggetto file scade (quando nulla si riferisce ad esso). In questo caso poiché nulla fa riferimento all'oggetto file dopo essere stato restituito da open (), verrà chiuso non appena il carico ritorna. Questa non è considerata una buona pratica e causerà problemi su altri sistemi
Ankur S

14

In generale, il decapaggio a dictfallirà a meno che non ci siano solo oggetti semplici, come stringhe e numeri interi.

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

Anche un semplice davverodict spesso fallirà. Dipende solo dal contenuto.

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

Tuttavia, se si utilizza un serializzatore migliore come dillo cloudpickle, la maggior parte dei dizionari può essere decapata:

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

O se vuoi salvare il tuo dictin un file ...

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

Quest'ultimo esempio è identico a una qualsiasi delle altre buone risposte pubblicate qui (che oltre a trascurare la possibilità di scegliere il contenuto del contenuto dict).


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

normalmente è preferibile usare l'implementazione di 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.

6

Se vuoi solo memorizzare il dict in un singolo file, usa picklecosì

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)

Se si desidera salvare e ripristinare più dizionari in più file per la memorizzazione nella cache e archiviare dati più complessi, utilizzare anycache . Fa tutte le altre cose di cui hai bisogno in giropickle

from anycache import anycache

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

Anycache memorizza i diversi myfuncrisultati a seconda degli argomenti in diversi filecachedir e li ricarica.

Vedere la documentazione per ulteriori dettagli.


6

Modo semplice per scaricare i dati di Python (ad es. Dizionario) in un file pickle.

import pickle

your_dictionary = {}

pickle.dump(your_dictionary, open('pickle_file_name.p', 'wb'))

3
import pickle

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

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()

-8

Ho trovato il sottaceto confuso (forse perché sono spesso). Ho scoperto che funziona, però:

myDictionaryString=str(myDictionary)

Che è quindi possibile scrivere in un file di testo. Ho smesso di provare a usare pickle mentre stavo ricevendo errori che mi dicevano di scrivere numeri interi in un file .dat. Mi scuso per non aver usato il sottaceto.


1
-1: Dovrebbe salvarlo così com'è (cioè un oggetto Python) in modo che possiamo leggerlo in seguito senza ore in attesa di eseguirlo di nuovo. Pickle ci consente di memorizzare un oggetto Python da leggere in seguito.
Catbuilt

Questa è una vecchia risposta che ritorna nella coda dei messaggi di bassa qualità. Non è una cattiva soluzione in quanto probabilmente funziona con dizionari molto semplici, ma è molto ragionevole per dictcontenere un'ulteriore profondità di oggetti (che può essere stampata solo da nome) e / o oggetti senza alcuna o una rappresentazione di stringa completa.
ti7

1
Per aggiungere al punto di @ ti7, indipendentemente dal merito tecnico della risposta, questo post non è VLQ. Se qualcuno ritiene che questa risposta sia inaccurata, dovrebbe sottovalutare e / o commentare spiegando il perché, non contrassegnarla come VLQ.
EJoshuaS - Ripristina Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.