Por que obtenho “Pickle - EOFError: Ficou sem entrada” lendo um arquivo vazio?

109

Estou recebendo um erro interessante ao tentar usar Unpickler.load(), aqui está o código-fonte:

open(target, 'a').close()
scores = {};
with open(target, "rb") as file:
    unpickler = pickle.Unpickler(file);
    scores = unpickler.load();
    if not isinstance(scores, dict):
        scores = {};

Aqui está o traceback:

Traceback (most recent call last):
File "G:\python\pendu\user_test.py", line 3, in <module>:
    save_user_points("Magix", 30);
File "G:\python\pendu\user.py", line 22, in save_user_points:
    scores = unpickler.load();
EOFError: Ran out of input

O arquivo que estou tentando ler está vazio. Como posso evitar esse erro e, em vez disso, obter uma variável vazia?

Magix
fonte
Não feche o arquivo
Alkesh Mahajan
A primeira linha open(...).close()está aqui para garantir que o arquivo existe
Magix

Respostas:

126

Gostaria de verificar se o arquivo não está vazio primeiro:

import os

scores = {} # scores is an empty dict already

if os.path.getsize(target) > 0:      
    with open(target, "rb") as f:
        unpickler = pickle.Unpickler(f)
        # if file is not empty scores will be equal
        # to the value unpickled
        scores = unpickler.load()

Também não open(target, 'a').close()está fazendo nada em seu código e você não precisa usar ;.

Padraic Cunningham
fonte
open (target, 'a'). close () está aqui para ter certeza de que o arquivo existe ;-) + Eu não preciso usar, ;mas acabei de chegar de C, e não usar ;no final das minhas linhas me faz chorar TT
Magix
ok, mas a instância é desnecessária, pois imagino que você só irá decifrar um dicionário, verificar se há um arquivo vazio será suficiente
Padraic Cunningham
além disso, verificar se o arquivo não está vazio nem sempre significará que posso retirá-lo ... levantando uma exceção ... É por isso que não acho que sua resposta não seja a melhor, mesmo que não seja ruim.
Magix
2
capturar um EOF exceptionnão o salvará de todos os outros erros potenciais.
Padraic Cunningham
1
você pode verificar se existe um arquivo usando o módulo os também, pode ser melhor do que abrir e fechar um arquivo todas as vezes.
Padraic Cunningham
131

A maioria das respostas aqui tratou de como gerenciar exceções EOFError, o que é realmente útil se você não tiver certeza se o objeto em conserva está vazio ou não.

No entanto, se você estiver surpreso que o arquivo pickle esteja vazio, pode ser porque você abriu o nome do arquivo por meio de 'wb' ou algum outro modo que poderia ter sobrescrito o arquivo.

por exemplo:

filename = 'cd.pkl'
with open(filename, 'wb') as f:
    classification_dict = pickle.load(f)

Isso substituirá o arquivo em conserva. Você pode ter feito isso por engano antes de usar:

...
open(filename, 'rb') as f:

E então obteve o EOFError porque o bloco de código anterior sobrescreveu o arquivo cd.pkl.

Quando trabalho no Jupyter ou no console (Spyder), geralmente escrevo um wrapper sobre o código de leitura / gravação e chamo o wrapper posteriormente. Isso evita erros comuns de leitura e gravação e economiza um pouco de tempo se você for ler o mesmo arquivo várias vezes durante o trabalho

Abhay Nainan
fonte
43
However, if you're surprised that the pickle file is empty, it could be because you opened the filename through 'wb' or some other mode that could have over-written the fileIsso fez você ganhar +1
Neb
10
Eu apenas fiz isso; realmente aprecio esta nota (estou feliz por não ser o único!)
zlipp
8
também o substituímos antes com "wb". +1
gebbissimo
5
Às vezes, o óbvio não é nada óbvio! Obrigado :)
jerpint
necessidade de bloqueio de arquivo - Esta resposta ajudaria muitas pessoas, eu estava tentando ler o arquivo enquanto ele estava aberto para gravação.
aspiring1 de
8

Como você pode ver, isso é realmente um erro natural.

Uma construção típica para leitura de um objeto Unpickler seria assim ..

try:
    data = unpickler.load()
except EOFError:
    data = list()  # or whatever you want

EOFError é simplesmente gerado, porque estava lendo um arquivo vazio, significava apenas Fim do arquivo ..

Amr Ayman
fonte
6

É muito provável que o arquivo em conserva esteja vazio.

É surpreendentemente fácil substituir um arquivo pickle se você estiver copiando e colando o código.

Por exemplo, o seguinte grava um arquivo pickle:

pickle.dump(df,open('df.p','wb'))

E se você copiou este código para reabri-lo, mas se esqueceu de mudar 'wb'para 'rb', você substituiria o arquivo:

df=pickle.load(open('df.p','wb'))

A sintaxe correta é

df=pickle.load(open('df.p','rb'))
user2723494
fonte
1
Os dois últimos exemplos de código devem ser trocados, certo?
Daniello
@Daniello eu fiz. Obrigado. Está revisado.
user2723494
3
if path.exists(Score_file):
      try : 
         with open(Score_file , "rb") as prev_Scr:

            return Unpickler(prev_Scr).load()

    except EOFError : 

        return dict() 
jukoo
fonte
2
Olá e bem-vindo ao Stackoverflow. Você pode explicar este código um pouco, por favor?
Alexander
2

Você pode capturar essa exceção e retornar o que quiser de lá.

open(target, 'a').close()
scores = {};
try:
    with open(target, "rb") as file:
        unpickler = pickle.Unpickler(file);
        scores = unpickler.load();
        if not isinstance(scores, dict):
            scores = {};
except EOFError:
    return {}
Jramirez
fonte
10
O problema com isso é que ele vai esconder silenciosamente os arquivos corrompidos.
Ross Ridge
0

Observe que o modo de abertura de arquivos é 'a' ou algum outro com alfabeto 'a' também causará erro devido à substituição.

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
ualia Q
fonte