Estou tentando salvar e carregar objetos usando o pickle
módulo.
Primeiro eu declaro meus objetos:
>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
Depois disso, abro um arquivo chamado 'Fruits.obj' (anteriormente, criei um novo arquivo .txt e renomeei 'Fruits.obj'):
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
Depois disso fecho minha sessão e inicio uma nova e coloco a seguinte (tentando acessar o objeto que deveria ser salvo):
file = open("Fruits.obj",'r')
object_file = pickle.load(file)
Mas eu tenho esta mensagem:
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
Não sei o que fazer porque não entendo esta mensagem. Alguém sabe como posso carregar meu objeto 'banana'? Obrigado!
EDIT: Como alguns de vocês sugeriram eu coloco:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
Não houve problema, mas o próximo que coloquei foi:
>>> object_file = pickle.load(file)
E eu tenho erro:
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
Respostas:
Quanto ao seu segundo problema:
Depois de ler o conteúdo do arquivo, o ponteiro do arquivo estará no final do arquivo - não haverá mais dados para ler. Você deve retroceder o arquivo para que seja lido desde o início novamente:
O que você geralmente deseja fazer, porém, é usar um gerenciador de contexto para abrir o arquivo e ler os dados dele. Dessa forma, o arquivo será fechado automaticamente após a execução do bloco, o que também o ajudará a organizar as operações do arquivo em partes significativas.
Finalmente, cPickle é uma implementação mais rápida do módulo pickle em C. Então:
fonte
{"a": 1, "b": 2}
cria um dicionário com as chaves"a"
e"b"
nele. Isso é chamado de expressão de exibição de dicionário na documentação online. É apenas uma das várias maneiras diferentes dedict
construir um objeto do tipo , que é um dos vários tipos de dados internos padrão disponíveis no Python.pickle
que irá importarcpickle
automaticamente se puder. docs.python.org/3.1/whatsnew/3.0.html#library-changesO seguinte funciona para mim:
fonte
class Fruits
definido para quepickle.load()
possa reconstituir o objeto a partir dos dados que foram salvos no arquivo binário. A melhor prática para esse tipo de coisa é colocar aclass Fruits
definição em um arquivo .py separado (tornando-o um módulo personalizado) e, em seguida,import
esse módulo ou itens dele sempre que necessário (ou seja, ambas as sessões). Por exemplo, se você colocá-lo em um arquivo chamadoMyDataDefs.py
, poderá escreverfrom MyDataDefs import Fruits
. Avise-me se não estiver claro e atualizarei minha resposta de acordo.my_data_defs.py
usingfrom my_data_defs import Fruits
.Você está se esquecendo de ler como binário também.
Em sua parte de escrita, você tem:
Na parte de leitura você tem:
Portanto, substitua-o por:
E vai funcionar :)
Quanto ao seu segundo erro, é mais provável que seja causado por não fechar / sincronizar o arquivo corretamente.
Experimente este código para escrever:
E isso (inalterado) para ler:
Uma versão mais limpa estaria usando a
with
declaração.Para escrever:
Para ler:
fonte
Sempre aberto no modo binário, neste caso
fonte
Você não abriu o arquivo no modo binário.
Deveria trabalhar.
Para o seu segundo erro, o arquivo provavelmente está vazio, o que significa que você o esvaziou inadvertidamente ou usou o nome de arquivo errado ou algo assim.
(Isso pressupõe que você realmente fechou sua sessão. Caso contrário, é porque você não fechou o arquivo entre a gravação e a leitura).
Testei seu código e funciona.
fonte
Parece que você deseja salvar suas instâncias de classe entre as sessões e usar
pickle
é uma maneira decente de fazer isso. No entanto, há um pacote chamadoklepto
que abstrai o salvamento de objetos em uma interface de dicionário, então você pode escolher separar objetos e salvá-los em um arquivo (como mostrado abaixo), ou separar os objetos e salvá-los em um banco de dados, ou em vez de use pickle use json ou muitas outras opções. O bomklepto
disso é que, abstraindo para uma interface comum, torna-se mais fácil para que você não precise se lembrar dos detalhes de baixo nível de como salvar por meio da separação em um arquivo ou de outra forma.Observe que funciona para atributos de classe adicionados dinamicamente, que o pickle não pode fazer ...
Então nós recomeçamos ...
Klepto
funciona em python2 e python3.Obtenha o código aqui: https://github.com/uqfoundation
fonte
Você pode usar qualquer cache para fazer o trabalho por você. Supondo que você tenha uma função
myfunc
que cria a instância:Anycache chama
myfunc
na primeira vez e seleciona o resultado para um arquivocachedir
usando um identificador exclusivo (dependendo do nome da função e dos argumentos) como nome de arquivo. Em qualquer execução consecutiva, o objeto conservado é carregado.Se o
cachedir
for preservado entre as execuções do Python, o objeto em conserva será obtido da execução anterior do Python.Os argumentos da função também são levados em consideração. Uma implementação refatorada funciona da mesma forma:
fonte