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?


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


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


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


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

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

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

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')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.