Perché ricevo "Pickle - EOFError: Ran out of input" leggendo un file vuoto?


109

Ricevo un errore interessante durante il tentativo di utilizzo Unpickler.load(), ecco il codice sorgente:

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

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

Il file che sto cercando di leggere è vuoto. Come posso evitare di ottenere questo errore e ottenere invece una variabile vuota?


Non chiudere il file
Alkesh Mahajan

La prima riga open(...).close()è qui per garantire che il file esista
Magix

Risposte:


126

Vorrei prima controllare che il file non sia vuoto:

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

Inoltre non open(target, 'a').close()sta facendo nulla nel codice e non è necessario utilizzarlo ;.


open (target, 'a'). close () è qui per assicurarmi che il file esista ;-) + Non ho bisogno di usare ;ma sono appena arrivato da C, e non usare ;alla fine delle mie righe fa il mio pianto TT
Magix

ok, ma la questione non è necessaria perché immagino che starai solo decapando un dict, sarà sufficiente controllare un file vuoto
Padraic Cunningham

inoltre, controllare che il file non sia vuoto non significa sempre che io possa rimuoverlo ... sollevando un'eccezione ... Ecco perché non penso che la tua risposta non sia la migliore, anche se non è male.
Magix

2
catturarlo EOF exceptionnon ti salverà da tutti gli altri potenziali errori.
Padraic Cunningham

1
puoi controllare se un file esiste anche usando il modulo os, potrebbe essere meglio che aprire e chiudere un file ogni volta.
Padraic Cunningham

131

La maggior parte delle risposte qui si è occupata di come gestire le eccezioni EOFError, che è davvero utile se non sei sicuro che l'oggetto in salamoia sia vuoto o meno.

Tuttavia, se sei sorpreso che il file pickle sia vuoto, potrebbe essere perché hai aperto il nome del file tramite 'wb' o qualche altra modalità che potrebbe aver sovrascritto il file.

per esempio:

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

Questo sovrascriverà il file in salamoia. Potresti averlo fatto per errore prima di utilizzare:

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

E poi ha ottenuto l'EOFError perché il blocco di codice precedente ha sovrascritto il file cd.pkl.

Quando lavoro in Jupyter o nella console (Spyder) di solito scrivo un wrapper sul codice di lettura / scrittura e chiamo il wrapper successivamente. Ciò evita errori comuni di lettura / scrittura e consente di risparmiare un po 'di tempo se stai per leggere lo stesso file più volte durante i tuoi travagli


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 fileQuesto ti ha fatto vincere +1
Nab

10
L'ho appena fatto; apprezzo molto questa nota (sono contento di non essere l'unico!)
zlipp

8
l'ho anche sovrascritto prima con "wb". +1
gebbissimo

5
A volte l'ovvio non è affatto ovvio! Grazie :)
jerpint

necessità di blocco dei file - Questa risposta aiuterebbe molte persone, stavo cercando di leggere il file mentre era aperto per la scrittura.
aspiranti 1

8

Come vedi, in realtà è un errore naturale ..

Un tipico costrutto per la lettura da un oggetto Unpickler sarebbe come questo ..

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

EOFError viene semplicemente sollevato, perché stava leggendo un file vuoto, significava solo End of File ..


6

È molto probabile che il file decapato sia vuoto.

È sorprendentemente facile sovrascrivere un file pickle se stai copiando e incollando codice.

Ad esempio, quanto segue scrive un file pickle:

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

E se è stato copiato il codice di riaprirlo, ma ha dimenticato di cambiare 'wb'per 'rb'allora si sarebbe sovrascrivere il file:

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

La sintassi corretta è

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

1
Gli ultimi due esempi di codice dovrebbero essere scambiati, giusto?
Daniello

@Daniello l'ho fatto. Grazie. È stato rivisto.
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
Ciao e benvenuto in Stackoverflow. Puoi spiegare un po 'questo codice per favore?
Alexander

2

Puoi catturare quell'eccezione e restituire quello che vuoi da 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
Il problema con questo è che nasconderà silenziosamente i file danneggiati.
Ross Ridge

0

Si noti che la modalità di apertura dei file è "a" o altri hanno l'alfabeto "a" anche per errore a causa della sovrascrittura.

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.