Чому я отримую "Pickle - EOFError: Закінчилося введення", читаючи порожній файл?


109

Я отримую цікаву помилку під час спроби використання Unpickler.load(), ось вихідний код:

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

Ось простеження:

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

Файл, який я намагаюся прочитати, порожній. Як я можу уникнути отримання цієї помилки та замість цього отримати порожню змінну?


Не закривайте файл
Алкеш Махаджан

Перший рядок open(...).close()- тут, щоб переконатися, що файл існує
Magix

Відповіді:


126

Я би переконався, що файл спочатку не порожній:

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

Також open(target, 'a').close()у вашому коді нічого не робиться, і вам не потрібно користуватися ;.


відкрити (target, 'a'). close () тут, щоб переконатися, що файл існує ;-) + Мені не потрібно користуватися, ;але я щойно прийшов із C, і не використовуючи ;в кінці рядків змушую плакати TT
Magix

Гаразд, але істота не потрібна, як я думаю, ви збираєтеся лише добирати дік, перевіряти наявність порожнього файлу буде достатньо
Padraic Cunningham

окрім того, перевірка файлу не порожній не завжди означатиме, що я можу його зняти ... піднявши виняток ... Ось чому я не думаю, що ваша відповідь не найкраща, навіть я вважав, що це не погано.
Magix

2
виловлення EOF exceptionне вбереже вас від усіх інших потенційних помилок.
Padraic Cunningham

1
Ви можете перевірити, чи існує файл, використовуючи також модуль os, може бути краще, ніж відкривати та закривати файл кожного разу.
Padraic Cunningham

131

Більшість відповідей тут стосувалися способів управління винятками EOFError, що дуже зручно, якщо ви не впевнені, чи маринований об’єкт порожній чи ні.

Однак, якщо ви здивовані, що файл соління порожній, це може бути тому, що ви відкрили ім'я файлу через 'wb' або інший режим, який міг перезаписати файл.

наприклад:

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

Це дозволить перезаписати маринований файл. Ви могли зробити це помилково перед використанням:

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

А потім отримав EOFError, оскільки попередній блок коду переписав файл cd.pkl.

Під час роботи в Jupyter або в консолі (Spyder) я зазвичай пишу обгортку над кодом для читання / запису, а потім дзвоню в обгортку. Це дозволяє уникнути поширених помилок читання-запису та економить трохи часу, якщо ви збираєтесь читати один і той же файл кілька разів через ваші дорожні потоки


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 fileЦе змусило вас виграти +1
Неб

10
Я щойно це зробив; дуже ціную цю замітку (радий, що я не єдиний!)
zlipp

8
також перезаписали його раніше з "wb". +1
gebbissimo

5
Іноді очевидне зовсім не очевидне! Дякую :)
jerpint

необхідність блокування файлів - ця відповідь допоможе багатьом людям, я намагався прочитати файл, поки він був відкритим для запису.
aspiring1

8

Як бачите, це насправді природна помилка ..

Типова конструкція для читання з об’єкта Unpickler буде такою.

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

EOFError просто піднімається, тому що він читав порожній файл, він просто означав Кінець файлу ..


7

Дуже ймовірно, що маринований файл порожній.

На диво легко перезаписати файл соління, якщо ви копіюєте та вставляєте код.

Наприклад, записує файл соління:

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

І якщо ви скопіювали цей код для його повторного відкриття, але забули змінити 'wb'його, 'rb'ви б перезаписали файл:

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

Правильний синтаксис є

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

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
Привітання та привітання до Stackoverflow. Чи можете ви трохи поясніть цей код?
Олександр

2

Ви можете зловити це виняток і повернути звідти все, що завгодно.

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
Проблема з цим полягає в тому, що він буде мовчки приховувати пошкоджені файли.
Росс Ридж

0

Зауважте, що режим відкриття файлів "a" або якийсь інший має алфавіт "a" також призведе до помилок через перезапис.

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.