【问题标题】:cPickle: UnpicklingError: invalid load key, 'A'cPickle:UnpicklingError:无效的加载键,'A'
【发布时间】:2016-10-03 11:09:52
【问题描述】:

我有一个 pickle 文件,在 unpickling 时会引发 UnpicklingError: invalid load key, 'A'. 异常。无论我是尝试在生成文件的 Ubuntu 14.04 机器上还是在我的 Windows 机器上分析它,都会引发异常。它包含 26 个数据点,并且在数据点 11 之后引发异常。我怀疑我一定是不小心编辑了文件,尽管我不知道何时或如何。我知道关于这种错误还有其他几个讨论,但到目前为止,我还没有找到一个帖子告诉我是否以及如何在错误输入后恢复这些值(我怀疑其中一个值已经无法挽回地丢失了)。有什么办法可以跳过它并继续解开下一个?可以一个例如以相反的方向解开,即最后一个元素首先?然后我可以向后工作,直到我遇到错误的条目,从而获得其他值。 (我可以重新生成数据,但这需要一两天的时间,所以如果可以的话,我宁愿避免这样做。)

这是酸洗的代码:

with open('hist_vs_years2.pkl', 'ab') as hist_pkl:
        pickle.dump(hist, hist_pkl, -1)

这是unpickling的代码:

hist_vs_samples2 = []
more_values = True

with open('hist_vs_years2.pkl', 'rb') as hist_vs_samples_pkl:
    while more_values == True:
        try:
            hist_vs_samples2.append(pickle.load(hist_vs_samples_pkl))
        except EOFError:
            more_values = False

我应该补充一点,我正在使用 cPickle。如果我尝试使用 pickle 进行 unpickle,则会收到以下错误:

  File "C:\Anaconda2\lib\pickle.py", line 1384, in load
    return Unpickler(file).load()

  File "C:\Anaconda2\lib\pickle.py", line 864, in load
    dispatch[key](self)

KeyError: 'A'

【问题讨论】:

  • 请贴出pickle文件的相关部分。您的存储代码表明您只有一个对象,在这种情况下,您必须修复加载键,因为无法部分加载腌制对象。如果您实际上存储了多个对象(不是多个对象的列表),则可以删除损坏的对象。如果您想自己执行此操作,pickle.py 源会列出加载键,这也说明了格式。
  • 抱歉,酸洗代码位于一个更大的循环中。它们确实是独立的对象。我如何识别泡菜文件的相关部分,你知道吗?同时我会尝试在网上找到解释。
  • 恐怕酸洗文件并不意味着用户可读。你必须自己去挖掘它;为了更简单,打印所有工作对象的索引,然后从那里开始搜索。
  • 浏览我的文件似乎条目以€]q(cnumpy.core.multiarray\n_reconstruct 开头并以tbe. 结尾所以我删除了第十二个条目。现在解开它似乎有趣地按预期准确地加载了所有 27 个整体,所以我不确定那里出了什么问题(由于某种原因,必须插入一个额外的、损坏的条目)但非常感谢您的帮助!如果您想将您的评论变成答案,我很乐意接受。
  • 不要使用 pickle,很容易损坏(例如 UnpicklingError: invalid load key, '\x00'.)使用替代品。泡菜不够强。如果损坏,唯一的解决方案是删除它并创建一个新的(即:不可恢复)

标签: python python-2.7 pickle


【解决方案1】:

当存储多个对象(通过重复的dump,而不是从容器中)时,Pickle 会将对象顺序存储在 pickle 文件中,因此如果一个对象被破坏,它可以被删除而不会破坏其他对象。

原则上,pickle 格式在pickle.py 中被伪记录。在大多数情况下,模块开头的操作码足以拼凑正在发生的事情。基本上,pickle 文件是关于如何构建对象的说明。

pickle 文件的可读性取决于它的 pickle 格式 - 0 是可行的,上面的一切都是困难。您是否可以修复或必须删除完全取决于此。一致的是,每个单独的泡菜都以一个点 (.) 结尾。例如,b'Va\np0\n.'b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00\x8c\x01a\x94.' 都是字符“a”,但在协议 0 和 4 中。

最简单的恢复形式是计算可以加载的对象数量:

with open('/my/pickle.pkl', 'rb') as pkl_source:
    idx = 1
    while True:
        pickle.load(pkl_source)
        print(idx)
        idx += 1

然后打开 pickle 文件,跳过尽可能多的对象并删除所有内容,直到下一个 .

【讨论】:

    猜你喜欢
    • 2011-12-28
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 2021-07-10
    相关资源
    最近更新 更多