为什么我在读取空文件时会收到“Pickle - EOFError: Ran out of input”?

问题描述 投票:0回答:13

我在尝试使用

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

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

python file pickle
13个回答
338
投票

这里的大多数答案都涉及如何管理 EOFError 异常,如果您不确定 pickled 对象是否为空,这真的很方便。

但是,如果您对 pickle 文件为空感到惊讶,可能是因为您通过“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) 中工作时,我通常会在读/写代码上编写一个包装器,然后调用该包装器。这可以避免常见的读写错误,如果您要多次读取同一个文件,还可以节省一些时间


183
投票

我会先检查文件是否不为空:

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


29
投票

很有可能pickled文件是空的。

如果您复制并粘贴代码,覆盖 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'))

11
投票

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

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

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

EOFError 被简单地引发,因为它正在读取一个空文件,它只是意味着 文件结束 ..


4
投票

有同样的问题。事实证明,当我写入 pickle 文件时,我没有使用 file.close()。插入该行,错误就消失了。


3
投票

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

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

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

            return Unpickler(prev_Scr).load()

    except EOFError : 

        return dict() 

3
投票

我多次遇到这个错误,而且总是发生,因为写入文件后,我没有关闭它。如果我们不关闭文件,内容将保留在缓冲区中并且文件将保持为空。 要将内容保存到文件中,应关闭文件或 file_object 超出范围。

这就是为什么在加载时会出现

ran out of input
错误,因为文件是空的。所以你有两个选择:

  1. file_object.close()
  2. file_object.flush()
    :如果您不想在程序之间关闭文件,可以使用
    flush()
    函数,因为它会强制将内容从缓冲区移动到文件。

1
投票

当您的 pickle 文件为空(0 字节)时,会出现此错误。您需要首先检查 pickle 文件的大小。这就是我的案例中的情况。希望这有帮助!


0
投票

注意打开文件的模式为‘a’或者其他带有字母‘a’的文件也会因为覆盖而出错。

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

0
投票
temp_model = os.path.join(models_dir, train_type + '_' + part + '_' + str(pc))
# print(type(temp_model)) # <class 'str'>
filehandler = open(temp_model, "rb")
# print(type(filehandler)) # <class '_io.BufferedReader'>
try:
    pdm_temp = pickle.load(filehandler)
except UnicodeDecodeError:
    pdm_temp = pickle.load(filehandler, fix_imports=True, encoding="latin1")

0
投票

建议添加创建一个虚拟/临时文件,将数据保存到其中并将其移动到所需位置

dummy_path = "file_name.txt"
with open(dummy_path, mode="wb") as file:

-1
投票
from os.path import getsize as size
from pickle import *
if size(target)>0:
    with open(target,'rb') as f:
        scores={i:j for i,j in enumerate(load(f))}
else: scores={}

#第 1 行。 我们从库“OS”子库“path”导入函数“getsize”,并使用命令“as”将其重命名为更短的写作风格。重要的是我们只加载我们需要的一个函数,而不是整个库! 第 2 行。 相同的想法,但是当我们不知道我们将在一开始的代码中使用哪个模块时,我们可以使用命令“*”导入所有库。 第 3 行。 条件语句...如果文件大小>0(意味着 obj 不是空的)。 “目标”是应该提前预定义的变量。 只是一个例子: target=(r'd:\dir1\dir.2..\YourDataFile.bin') 4号线。 'With open(target) as file:' 任何文件的开放结构,你不需要使用 file.close()。它有助于避免一些典型的错误,例如“输入不足”或权限。 “rb”mod 表示“rea 二进制”,您只能从二进制文件中读取(加载)数据,但无法修改/重写它。 5号线。 应用于字典的列表理解方法.. 第 6 行。如果您的数据文件为空,它不会引发任何错误消息,而仅返回一个空字典。

© www.soinside.com 2019 - 2024. All rights reserved.