类似的问题在这里被问了无数次,但这一次略有不同。我有个泡菜文件不知何故被破坏了。我假设程序在保存的时候崩溃了。无论哪种方式,文件都不是空的,从其大小判断,其中包含所有/大部分信息。尝试使用pickle加载is会得到一个标准的EOFError: Ran out of input
错误。
我了解该文件已损坏,并了解它最有可能发生的原因。我的问题是,是否有办法以某种方式恢复其中的任何内容?
发布于 2021-11-08 15:23:08
也许你可以试试这段代码。首先,你必须填充你的文件(用零),使其至少是原始大小,可以更大(或者你可以改变一些代码,使这不是必要的)。
我修改了函数_Unpickler.load(),使其不会在异常时终止,并在取消酸选失败时返回其堆栈。堆栈似乎是一个列表,其中包含属性的名称和值,因此可以使用setattr()
将它们分配给创建的对象。
我的示例创建了一个对象,如果为read=False
,则对该对象进行pickle;如果为read=True
,则取消对可能损坏的文件的pickle。
import pickle
read = False # run once with False, then corrupt file and change to True
class AClass:
def __init__(unpickler, a, b, c):
unpickler.a = a
unpickler.b = b
unpickler.c = c
def load(unpickler):
"""Read a pickled object representation from the open file.
Return the reconstituted object hierarchy specified in the file.
"""
# Check whether Unpickler was initialized correctly. This is
# only needed to mimic the behavior of _pickle.Unpickler.dump().
if not hasattr(unpickler, "_file_read"):
raise pickle.UnpicklingError("Unpickler.__init__() was not called by "
"%s.__init__()" % (unpickler.__class__.__name__,))
unpickler._unframer = pickle._Unframer(unpickler._file_read, unpickler._file_readline)
unpickler.read = unpickler._unframer.read
unpickler.readline = unpickler._unframer.readline
unpickler.metastack = []
unpickler.stack = []
unpickler.append = unpickler.stack.append
unpickler.proto = 0
read = unpickler.read
dispatch = unpickler.dispatch
try:
while True:
key = read(1)
if not key:
return unpickler.stack
#raise EOFError
assert isinstance(key, pickle.bytes_types)
try:
dispatch[key[0]](unpickler)
except KeyError as e:
print("KeyError")
#dispatch[NONE[0]](unpickler)
except ValueError as e:
print("ValueError")
except pickle._Stop as stopinst:
print("Stop raised")
print(stopinst.value)
return stopinst.value
if not read:
# create an object and save it
obj = AClass(1,2,3)
with open("obj.pkl", 'wb') as outFile:
pickle.dump(obj, outFile, pickle.HIGHEST_PROTOCOL)
else:
# open the object
with (open("obj.pkl", "rb")) as inFile:
try:
unpickler = pickle._Unpickler(inFile)
obj = load(unpickler)
except Exception as e:
print(e)
# a list will be returned, if the unpickling fails
if isinstance(obj, list):
l = obj
print(l)
i = 0
obj = AClass(0,0,0)
while i < len(l)-1:
setattr(obj, l[i], l[i+1])
i += 2
print(obj.a, obj.b, obj.c)
https://stackoverflow.com/questions/69884950
复制相似问题