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

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

尝试使用时出现一个有趣的错误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

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

I am getting an interesting error while trying to use Unpickler.load(), here is the source code:

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

Here is the 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

The file I am trying to read is empty. How can I avoid getting this error, and get an empty variable instead?


回答 0

我先检查文件是否为空:

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

I would check that the file is not empty first:

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

Also open(target, 'a').close() is doing nothing in your code and you don’t need to use ;.


回答 1

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

Most of the answers here have dealt with how to mange EOFError exceptions, which is really handy if you’re unsure about whether the pickled object is empty or not.

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.

for example:

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

This will over-write the pickled file. You might have done this by mistake before using:

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

And then got the EOFError because the previous block of code over-wrote the cd.pkl file.

When working in Jupyter, or in the console (Spyder) I usually write a wrapper over the reading/writing code, and call the wrapper subsequently. This avoids common read-write mistakes, and saves a bit of time if you’re going to be reading the same file multiple times through your travails


回答 2

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

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

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

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

As you see, that’s actually a natural error ..

A typical construct for reading from an Unpickler object would be like this ..

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

EOFError is simply raised, because it was reading an empty file, it just meant End of File ..


回答 3

腌制的文件很可能为空。

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

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

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

而且,如果您复制以下代码以重新打开它,但忘记更改'wb''rb',则将覆盖文件:

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

正确的语法是

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

It is very likely that the pickled file is empty.

It is surprisingly easy to overwrite a pickle file if you’re copying and pasting code.

For example the following writes a pickle file:

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

And if you copied this code to reopen it, but forgot to change 'wb' to 'rb' then you would overwrite the file:

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

The correct syntax is

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

回答 4

if path.exists(Score_file):
      try : 
         with open(Score_file , "rb") as prev_Scr:

            return Unpickler(prev_Scr).load()

    except EOFError : 

        return dict() 
if path.exists(Score_file):
      try : 
         with open(Score_file , "rb") as prev_Scr:

            return Unpickler(prev_Scr).load()

    except EOFError : 

        return dict() 

回答 5

您可以捕获该异常并从那里返回您想要的任何东西。

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 {}

You can catch that exception and return whatever you want from there.

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 {}

回答 6

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

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

Note that the mode of opening files is ‘a’ or some other have alphabet ‘a’ will also make error because of the overwritting.

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