为什么在读取一个空文件时出现“ Pickle-EOFError:Ran out of input”的问题?


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

我尝试读取的文件为空。如何避免出现此错误,而是获取一个空变量?


不要关闭文件
Alkesh Mahajan

第一行open(...).close()是为了确保文件存在
Magix

Answers:


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()在您的代码中什么也不做,您不需要使用;


open(target,'a')。close()在这里以确保文件存在;-) +我不需要使用,;但是我只是来自C,而;我的行末不使用使我哭泣TT
Magix 2014年

好的,但是不需要这样,因为我想您只是要腌制一份字典,检查空文件就足够了
Padraic Cunningham

此外,检查文件是否为空并不总是意味着可以解开文件……引发异常……这就是为什么我不认为您的答案不是最好的,甚至认为还不错。
Magix

2
捕获EOF exception并不能将您从所有其他潜在错误中解救出来。
Padraic Cunningham 2014年

1
您也可以使用os模块检查文件是否存在,这可能比每次打开和关闭文件都要好。
Padraic Cunningham 2014年

130

这里的大多数答案都涉及如何处理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)中工作时,我通常会在读取/写入代码上编写一个包装器,然后再调用该包装器。这样可以避免常见的读写错误,并且如果您要多次通过同一个文件读取同一文件,可以节省一些时间。


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 file这使您赢得+1
Neb

10
我就是这样做的;非常感激此笔记(我很高兴我不是唯一的
笔记

8
之前也用“ wb”覆盖了它。+1
gebbissimo'1

5
有时显而易见的东西根本就不明显!谢谢:)
jerpint

文件锁定的必要性 -这个答案将对很多人有帮助,我正在尝试打开可写的文件。
aspiring1

8

如您所见,这实际上是一个自然错误..

从Unpickler对象读取的典型构造如下:

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

只是引发EOFError,因为它正在读取一个空文件,这仅表示文件末尾 ..


7

腌制的文件很可能为空。

如果要复制和粘贴代码,则覆盖腌制文件非常容易。

例如,以下内容编写了一个pickle文件:

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
这样做的问题是它将以静默方式隐藏损坏的文件。
Ross Ridge)

0

请注意,打开文件的模式为'a'或其他一些带有字母'a'的模式也会由于覆盖过多而出错。

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.