Warum erhalte ich beim Lesen einer leeren Datei die Meldung "Pickle - EOFError: Keine Eingabe mehr"?

109

Beim Versuch, es zu verwenden Unpickler.load(), wird ein interessanter Fehler angezeigt . Hier ist der Quellcode:

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

Hier ist der 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

Die Datei, die ich zu lesen versuche, ist leer. Wie kann ich diesen Fehler vermeiden und stattdessen eine leere Variable erhalten?

Magix
quelle
Schließen Sie die Datei nicht
Alkesh Mahajan
Die erste Zeile open(...).close()ist hier, um sicherzustellen, dass die Datei existiert
Magix

Antworten:

126

Ich würde zuerst überprüfen, ob die Datei nicht leer ist:

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

Auch open(target, 'a').close()tut nichts in Ihrem Code und Sie müssen nicht verwenden ;.

Padraic Cunningham
quelle
open (target, 'a'). close () ist hier, um sicherzustellen, dass die Datei existiert ;-) + Ich muss sie nicht verwenden, ;aber ich komme gerade von C, und wenn ich sie nicht ;am Ende meiner Zeilen verwende, weine ich TT
Magix
ok, aber die Ausgabe ist unnötig, da ich mir vorstelle, dass Sie nur ein Diktat einarbeiten werden. Die Überprüfung auf eine leere Datei wird ausreichen
Padraic Cunningham
Außerdem bedeutet das Überprüfen, dass die Datei nicht leer ist, nicht immer, dass ich sie entfernen kann ... eine Ausnahme auslösen ... Deshalb denke ich nicht, dass Ihre Antwort nicht die beste ist, auch wenn sie nicht schlecht ist.
Magix
2
Das Fangen eines EOF exceptionwird Sie nicht vor allen anderen möglichen Fehlern bewahren.
Padraic Cunningham
1
Sie können auch mithilfe des OS-Moduls überprüfen, ob eine Datei vorhanden ist. Dies ist möglicherweise besser, als jedes Mal eine Datei zu öffnen und zu schließen.
Padraic Cunningham
129

Die meisten Antworten hier haben sich mit dem Verwalten von EOFError-Ausnahmen befasst. Dies ist sehr praktisch, wenn Sie sich nicht sicher sind, ob das eingelegte Objekt leer ist oder nicht.

Wenn Sie jedoch überrascht sind, dass die Pickle-Datei leer ist, kann dies daran liegen, dass Sie den Dateinamen über 'wb' oder einen anderen Modus geöffnet haben, der die Datei möglicherweise überschrieben hat.

beispielsweise:

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

Dadurch wird die eingelegte Datei überschrieben. Möglicherweise haben Sie dies versehentlich getan, bevor Sie Folgendes verwendet haben:

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

Und dann den EOFError bekommen, weil der vorherige Codeblock die Datei cd.pkl überschrieben hat.

Wenn ich in Jupyter oder in der Konsole (Spyder) arbeite, schreibe ich normalerweise einen Wrapper über den Lese- / Schreibcode und rufe den Wrapper anschließend auf. Dies vermeidet häufige Lese- / Schreibfehler und spart ein wenig Zeit, wenn Sie dieselbe Datei mehrmals durch Ihre Schwierigkeiten lesen

Abhay Nainan
quelle
42
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 fileDies brachte Sie dazu, +1
Neb
10
Ich habe das gerade getan; Ich schätze diese Notiz wirklich (ich bin froh, dass ich nicht der einzige bin!)
zlipp
8
habe es auch schon mal mit "wb" überschrieben. +1
gebbissimo
5
Manchmal ist das Offensichtliche überhaupt nicht offensichtlich! Danke :)
Jerpint
Notwendigkeit der Dateisperrung - Diese Antwort würde vielen Menschen helfen. Ich habe versucht, die Datei zu lesen, während sie zum Schreiben geöffnet war.
aspiring1
8

Wie Sie sehen, ist das eigentlich ein natürlicher Fehler.

Ein typisches Konstrukt zum Lesen aus einem Unpickler-Objekt wäre wie folgt.

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

EOFError wird einfach ausgelöst, weil es eine leere Datei las, es bedeutete nur Dateiende .

Amr Ayman
quelle
7

Es ist sehr wahrscheinlich, dass die eingelegte Datei leer ist.

Es ist überraschend einfach, eine Pickle-Datei zu überschreiben, wenn Sie Code kopieren und einfügen.

Zum Beispiel schreibt das Folgende eine Pickle-Datei:

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

Und wenn Sie diesen Code kopiert haben, um ihn erneut zu öffnen, aber vergessen haben, ihn zu ändern 'wb', 'rb'würden Sie die Datei überschreiben:

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

Die richtige Syntax lautet

df=pickle.load(open('df.p','wb'))
user2723494
quelle
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
quelle
2
Hellow und willkommen bei Stackoverflow. Können Sie diesen Code bitte etwas erklären?
Alexander
2

Sie können diese Ausnahme abfangen und von dort aus alles zurückgeben, was Sie möchten.

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
quelle
10
Das Problem dabei ist, dass beschädigte Dateien stillschweigend ausgeblendet werden.
Ross Ridge
0

Beachten Sie, dass der Modus zum Öffnen von Dateien 'a' ist oder ein anderes Alphabet 'a' aufgrund des Überschreibens ebenfalls Fehler macht.

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