Como posso usar pickle para salvar um ditado?

370

Examinei as informações que os documentos do Python fornecem, mas ainda estou um pouco confuso. Alguém poderia postar um exemplo de código que gravaria um novo arquivo e depois usar pickle para despejar um dicionário nele?

Chachmu
fonte
5
Leia isto: doughellmann.com/PyMOTW/pickle e volte quando precisar de uma pergunta específica
pyfunc
2
-1 Veja comentários anteriores. Tente. Então, se não funcionou (nem sempre), uma pergunta direcionada pode ser formulada (juntamente com uma hipótese ou duas que podem ser testadas e "consultadas", possivelmente antes de fazer a pergunta para outras pessoas). Por exemplo, houve um erro de sintaxe? Uma exceção? Os valores voltaram ilegíveis?
11
Eu tenho tentado usar isso para salvar informações do pygame. Usei as informações acima e meu código fica assim:
Chachmu
name = raw_input ( 'nome do arquivo de entrada:') tf = open (nome + 'PKL', 'wb') pickle.dump (total, tf) tf.close ()
Chachmu
2
Você deve fazer uma nova pergunta sobre como picles objetos de superfície
John La Rooy

Respostas:

727

Tente o seguinte:

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
Liquidificador
fonte
4
@houbysoft: Por que você removeu pickle.HIGHEST_PROTOCOL?
Blender
37
@ Blender: irrelevante e desnecessariamente complicado para esse nível de pergunta - o usuário médio ficará bem com os padrões.
houbysoft 25/12/16
28
@houbysoft: Verdadeiro para usuários do Python 3, mas no Python 2, o uso do protocolo padrão (0) não é apenas incrivelmente ineficiente no tempo e no espaço, mas na verdade não pode lidar com muitas coisas que o protocolo 2+ manipula muito bem (por exemplo, novas de estilo que usam __slots__). Não estou dizendo que você sempre deve usar HIGHEST_PROTOCOL, mas garantir que você não use o protocolo 0 ou 1 é realmente muito importante.
ShadowRanger 23/08
11
O que pickle.HIGHEST_PROTOCOLrealmente faz?
BallpointBen
7
@BallpointBen: Ele pega a maior versão do protocolo a sua versão do Python suporta: 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)

A vantagem HIGHEST_PROTOCOLé que os arquivos ficam menores. Isso faz com que a remoção de manchas às vezes seja muito mais rápida.

Aviso importante : O tamanho máximo do arquivo de pickle é de cerca de 2 GB.

Caminho alternativo

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

Formatos alternativos

Para seu aplicativo, o seguinte pode ser importante:

  • Suporte por outras linguagens de programação
  • Desempenho de leitura / escrita
  • Compacidade (tamanho do arquivo)

Consulte também: Comparação de formatos de serialização de dados

Caso você esteja procurando uma maneira de criar arquivos de configuração, leia meu pequeno artigo Arquivos de configuração em Python

Martin Thoma
fonte
11
Eu acho que o limite de 2 GB foi removido com o protocolo = 4 e 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"}
user3465692
fonte
11
é necessário usar um close () após o open ()?
precisa saber é o seguinte
11
Sim em geral. No entanto, no CPython (o python padrão que você provavelmente possui), o arquivo é fechado automaticamente sempre que o objeto do arquivo expira (quando nada se refere a ele). Nesse caso, como nada se refere ao objeto de arquivo após ser retornado por open (), ele será fechado assim que a carga retornar. Isto não é considerado uma boa prática e vai causar problemas em outros sistemas
Ankur S
14

Em geral, a escolha de a dictfalhará, a menos que você tenha apenas objetos simples, como seqüências de caracteres e números inteiros.

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

Mesmo um simples realmentedict falha frequentemente. Depende apenas do conteúdo.

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

No entanto, se você usar um serializador melhor como dillou cloudpickle, a maioria dos dicionários poderá ser configurada:

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

Ou se você quiser salvar o dictarquivo em um arquivo ...

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

O último exemplo é idêntico a qualquer uma das outras boas respostas postadas aqui (que além de negligenciar a escolha do conteúdo dictsão boas).

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

normalmente é preferível usar a implementação 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
fonte
6

Se você quiser apenas armazenar o dict em um único arquivo, use pickleassim

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 você deseja salvar e restaurar vários dicionários em vários arquivos para armazenar em cache e armazenar dados mais complexos, use anycache . Faz todas as outras coisas que você precisapickle

from anycache import anycache

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

O Anycache armazena os diferentes myfuncresultados, dependendo dos argumentos para diferentes arquivos, cachedire os recarrega.

Consulte a documentação para obter mais detalhes.

c0fec0de
fonte
6

Maneira simples de despejar dados do Python (por exemplo, dicionário) em um arquivo pickle.

import pickle

your_dictionary = {}

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

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

filename = "/foldername/filestore"

fileobj = open(filename, 'wb')

pickle.dump(dictobj, fileobj)

fileobj.close()
Rahul Nair
fonte
-8

Eu achei a decapagem confusa (possivelmente porque sou grossa). Descobri que isso funciona, no entanto:

myDictionaryString=str(myDictionary)

Que você pode gravar em um arquivo de texto. Desisti de tentar usar pickle, pois estava recebendo erros dizendo para escrever números inteiros em um arquivo .dat. Peço desculpas por não usar picles.

Pedro Rhian
fonte
11
-1: deve salvá-lo como está (ou seja, um objeto python) para que possamos lê-lo mais tarde, sem precisar esperar horas para executá-lo novamente. Pickle nos permite armazenar um objeto python para ler mais tarde.
Catbuilts
Essa é uma resposta antiga voltada para a fila de publicações de baixa qualidade. Não é uma solução ruim, pois provavelmente funciona para dicionários muito simples, mas é muito razoável que dicta contenha mais profundidade de objetos (que pode ser impressa apenas por nome) e / ou objetos sem nenhuma ou uma representação de string completa.
ti7 17/02
11
Para adicionar ao ponto de @ ti7, independentemente do mérito técnico da resposta, este post não é VLQ. Se alguém achar que essa resposta é imprecisa, faça um voto negativo e / ou comente explicando o motivo, não sinalize-a como VLQ.
EJoshuaS - Restabelece Monica