为什么读取空文件时会出现“Pickle - EOFError: Ran out of input”?

234 投票
13 回答
533095 浏览
提问于 2025-04-18 13:37

我在使用 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

我尝试读取的文件是空的。
我该如何避免这个错误,并得到一个空的变量呢?

13 个回答

5

我也遇到过同样的问题。原来是因为我在写入我的pickle文件时,没有使用file.close()这个命令。加上这一行后,错误就消失了。

12

如你所见,这其实是一个很常见的错误..

从一个Unpickler对象读取数据时,通常的写法是这样的..

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

EOFError这个错误出现的原因很简单,就是因为它在读取一个空文件,这意味着文件结束了..

30

很有可能这个被保存的文件是空的。

如果你在复制粘贴代码时,意外地覆盖了一个pickle文件,这其实是很容易发生的。

比如,下面这段代码会写入一个pickle文件:

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

如果你复制了这段代码来重新打开文件,但忘记把 'wb' 改成 'rb',那么你就会覆盖掉原来的文件:

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

正确的写法是

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

这里大部分回答都讲了怎么处理EOFError这种错误,这在你不确定保存的对象是否为空时特别有用。

不过,如果你发现pickle文件是空的,可能是因为你用'wb'模式打开了文件,或者用了其他可能会覆盖文件的模式。

比如:

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

这样做会覆盖掉之前的pickle文件。你可能在之前不小心就这样做了:

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

然后就因为之前的代码覆盖了cd.pkl文件而出现了EOFError错误。

在使用Jupyter或者Spyder控制台时,我通常会写一个封装函数来处理读写代码,然后再调用这个封装函数。这样可以避免常见的读写错误,如果你需要多次读取同一个文件,这样也能节省一些时间。

184

我建议你先检查一下文件是不是空的:

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() 在你的代码里其实没有做什么用,而且你也不需要用 ;

撰写回答