【问题标题】:Pickle. EOFError: Ran out of input. Can I recover any information from a corrupt pickle file?泡菜。 EOFError:输入不足。我可以从损坏的泡菜文件中恢复任何信息吗?
【发布时间】:2021-11-08 14:18:38
【问题描述】:

类似的问题在这里被问过很多次,但这次略有不同。我有一个以某种方式损坏的泡菜文件。我假设程序在保存过程中崩溃了。无论哪种方式,该文件都不是空的,并且根据其大小判断其中包含所有/大部分信息。尝试加载是用 pickle 给我一个标准的 EOFError: Ran out of input 错误。

我了解该文件已损坏,并且了解它发生的可能性有多大。我的问题是是否有办法以某种方式恢复它?

【问题讨论】:

  • 在某种程度上可能通过查看文件的python -m pickletools 的输出(如果它允许拆卸),然后进行一些仔细的手术,例如十六进制编辑器。

标签: python pickle


【解决方案1】:

也许试试这个代码。首先,您必须将文件(用零)填充为至少原始大小,可以更大(或者您可以更改一些代码以使其没有必要)。

我修改了函数 _Unpickler.load() 以在异常时不终止,并在 unpickling 失败时返回其堆栈。堆栈似乎是一个包含属性名称和值的列表,因此使用setattr() 您可以将它们分配给创建的对象。

如果read=False,我的示例创建一个对象来腌制,如果read=True,则取消腌制可能损坏的文件。

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多