¿Cómo puedo usar pickle para guardar un dict?

370

He revisado la información que proporcionan los documentos de Python , pero todavía estoy un poco confundido. ¿Alguien podría publicar un código de muestra que escribiría un nuevo archivo y luego usar pickle para volcar un diccionario en él?

Chachmu
fuente
55
Lea esto: doughellmann.com/PyMOTW/pickle y regrese cuando necesite una pregunta específica
pyfunc
2
-1 Ver comentarios anteriores. Intentalo. Luego, si no funcionó (no siempre), se puede formular una pregunta dirigida (junto con una hipótesis o dos que se pueden probar y "consultar", posiblemente antes de hacer la pregunta a otras personas). Por ejemplo, ¿hubo un error de sintaxis? ¿Una excepción? ¿Los valores volvieron confusos?
1
He estado tratando de usar esto para guardar información de pygame. He usado la información anterior y mi código se ve así:
Chachmu
name = raw_input ('input file name:') tf = open (name + '. pkl', 'wb') pickle.dump (total, tf) tf.close ()
Chachmu
2
Debería hacer una nueva pregunta sobre cómo encurtir objetos de superficie
John La Rooy

Respuestas:

728

Prueba esto:

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
Licuadora
fuente
44
@houbysoft: ¿Por qué eliminaste pickle.HIGHEST_PROTOCOL?
Blender
37
@Blender: irrelevante e innecesariamente complicado para este nivel de pregunta: el usuario promedio estará bien con los valores predeterminados.
houbysoft
28
@houbysoft: cierto para los usuarios de Python 3, pero en Python 2, usar el protocolo predeterminado (0) no solo es increíblemente ineficiente en tiempo y espacio, sino que en realidad no puede manejar muchas cosas que el protocolo 2+ maneja bien (por ejemplo, nuevo clases de estilo que usan __slots__). No digo que siempre deba usarlo HIGHEST_PROTOCOL, pero asegurarse de no usar el protocolo 0 o 1 es realmente bastante importante.
ShadowRanger
11
¿Qué hace pickle.HIGHEST_PROTOCOLrealmente?
BallpointBen
77
@BallpointBen: Elige la versión de protocolo más alta que su versión de Python admite: 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)

La ventaja de HIGHEST_PROTOCOLes que los archivos se hacen más pequeños. Esto hace que el desempaquetado sea a veces mucho más rápido.

Aviso importante : el tamaño máximo de archivo de pickle es de aproximadamente 2 GB.

Forma alternativa

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

Formatos alternativos

Para su aplicación, lo siguiente puede ser importante:

  • Soporte por otros lenguajes de programación.
  • Rendimiento de lectura / escritura
  • Compacidad (tamaño del archivo)

Ver también: Comparación de formatos de serialización de datos.

En caso de que esté buscando una manera de crear archivos de configuración, puede leer mi breve artículo Archivos de configuración en Python

Martin Thoma
fuente
1
Creo que el límite de 2 GB se eliminó con el protocolo = 4 y superior.
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"}
usuario3465692
fuente
1
¿Es necesario usar un close () después de open ()?
PlsWork
1
Si, en general. Sin embargo, en CPython (la python predeterminada que probablemente tenga) el archivo se cierra automáticamente cada vez que caduca el objeto del archivo (cuando nada se refiere a él). En este caso, dado que nada se refiere al objeto de archivo después de ser devuelto por open (), se cerrará tan pronto como regrese la carga. Esto no se considera una buena práctica y causará problemas en otros sistemas
Ankur S
14

En general, el decapado dictfallará a menos que solo tenga objetos simples, como cadenas y enteros.

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

Incluso un muy simple dicta menudo fallará. Solo depende de los contenidos.

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

Sin embargo, si usa un mejor serializador como dillo cloudpickle, entonces la mayoría de los diccionarios se pueden encurtir:

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

O si desea guardar su dicten un archivo ...

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

El último ejemplo es idéntico a cualquiera de las otras buenas respuestas publicadas aquí (que además de descuidar la capacidad de selección de los contenidos de la dictson buenas).

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

normalmente es preferible usar la implementación de 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
fuente
6

Si solo desea almacenar el dict en un solo archivo, use pickleasí

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 desea guardar y restaurar múltiples diccionarios en múltiples archivos para almacenar en caché y almacenar datos más complejos, use anycache . Hace todas las otras cosas que necesitas alrededorpickle

from anycache import anycache

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

Anycache almacena los diferentes myfuncresultados según los argumentos de los diferentes archivos cachediry los vuelve a cargar.

Consulte la documentación para más detalles.

c0fec0de
fuente
6

Manera simple de volcar datos de Python (por ejemplo, diccionario) en un archivo pickle.

import pickle

your_dictionary = {}

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

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

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()
Rahul Nair
fuente
-8

Encontré el encurtido confuso (posiblemente porque soy grueso). Sin embargo, descubrí que esto funciona:

myDictionaryString=str(myDictionary)

Que luego puede escribir en un archivo de texto. Dejé de intentar usar pickle porque recibía errores que me decían que escribiera enteros en un archivo .dat. Pido disculpas por no usar pepinillo.

Pedro Rhian
fuente
1
-1: Debería guardarlo tal como está (es decir, un objeto de Python) para que podamos leerlo más tarde sin horas esperando volver a ejecutarlo. Pickle nos permite almacenar un objeto python para leer más tarde.
Catbuilts
Esta es una vieja respuesta que regresa a la cola Publicaciones de baja calidad. No es una mala solución ya que probablemente funcione para diccionarios muy simples, pero es muy razonable dictque contenga una mayor profundidad de objetos (que puede imprimirse solo con nombre) y / u objetos sin ninguna o una representación de cadena completa.
ti7
1
Para agregar al punto de @ ti7, independientemente del mérito técnico de la respuesta, esta publicación no es VLQ. Si alguien siente que esta respuesta es inexacta, debe votar negativamente y / o comentar explicando por qué, no marcarla como VLQ.
EJoshuaS - Restablece a Monica