我在尝试使用
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
我试图读取的文件是空的。 如何避免出现此错误,并获得一个空变量?
这里的大多数答案都涉及如何管理 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) 中工作时,我通常会在读/写代码上编写一个包装器,然后调用该包装器。这可以避免常见的读写错误,如果您要多次读取同一个文件,还可以节省一些时间
我会先检查文件是否不为空:
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()
在您的代码中什么也不做,您不需要使用;
。
很有可能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'))
如您所见,这实际上是一个自然错误..
从 Unpickler 对象读取的典型构造如下 ..
try:
data = unpickler.load()
except EOFError:
data = list() # or whatever you want
EOFError 被简单地引发,因为它正在读取一个空文件,它只是意味着 文件结束 ..
有同样的问题。事实证明,当我写入 pickle 文件时,我没有使用 file.close()。插入该行,错误就消失了。
您可以捕获该异常并从那里返回您想要的任何内容。
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 {}
if path.exists(Score_file):
try :
with open(Score_file , "rb") as prev_Scr:
return Unpickler(prev_Scr).load()
except EOFError :
return dict()
我多次遇到这个错误,而且总是发生,因为写入文件后,我没有关闭它。如果我们不关闭文件,内容将保留在缓冲区中并且文件将保持为空。 要将内容保存到文件中,应关闭文件或 file_object 超出范围。
这就是为什么在加载时会出现
ran out of input
错误,因为文件是空的。所以你有两个选择:
file_object.close()
file_object.flush()
:如果您不想在程序之间关闭文件,可以使用 flush()
函数,因为它会强制将内容从缓冲区移动到文件。当您的 pickle 文件为空(0 字节)时,会出现此错误。您需要首先检查 pickle 文件的大小。这就是我的案例中的情况。希望这有帮助!
注意打开文件的模式为‘a’或者其他带有字母‘a’的文件也会因为覆盖而出错。
pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
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")
建议添加创建一个虚拟/临时文件,将数据保存到其中并将其移动到所需位置
dummy_path = "file_name.txt"
with open(dummy_path, mode="wb") as file:
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 行。如果您的数据文件为空,它不会引发任何错误消息,而仅返回一个空字典。