代码之家  ›  专栏  ›  技术社区  ›  hillu

如何恢复损坏的python“cPickle”转储?

  •  2
  • hillu  · 技术社区  · 15 年前

    我正在使用 rss2email 使用它是因为它今天以一种可怕的方式崩溃了:在每次跑步中,它只会给我这个回溯:

    Traceback (most recent call last):
      File "/usr/share/rss2email/rss2email.py", line 740, in <module>
        elif action == "list": list()
      File "/usr/share/rss2email/rss2email.py", line 681, in list
        feeds, feedfileObject = load(lock=0)
      File "/usr/share/rss2email/rss2email.py", line 422, in load
        feeds = pickle.load(feedfileObject)
    TypeError: ("'str' object is not callable", 'sxOYAAuyzSx0WqN3BVPjE+6pgPU', ((2009, 3, 19, 1, 19, 31, 3, 78, 0), {}))
    

    我能够从这个回溯构造的唯一有用的事实是文件 ~/.rss2email/feeds.dat 在哪儿 rss2email rss2email 读取其状态并使用 cPickle

    我甚至找到了那行 'sxOYAAuyzSx0WqN3BVPjE+6pgPU' feeds.dat 文件在我未经训练的眼中,垃圾堆似乎没有被截断或损坏。

    我可以尝试什么方法来重建文件?

    Python版本是Debian/不稳定系统上的2.5.4。

    编辑

    pickle文件,我以前也试过。显然,一个 Feed 这是在 rss2email.py

    #!/usr/bin/python
    
    import sys
    # import pickle
    import cPickle as pickle
    sys.path.insert(0,"/usr/share/rss2email")
    from rss2email import Feed
    
    feedfile = open("feeds.dat", 'rb')
    feeds = pickle.load(feedfile)
    

    Traceback (most recent call last):
      File "./r2e-rescue.py", line 8, in <module>
        feeds = pickle.load(feedfile)
      File "/usr/lib/python2.5/pickle.py", line 1370, in load
        return Unpickler(file).load()
      File "/usr/lib/python2.5/pickle.py", line 858, in load
        dispatch[key](self)
      File "/usr/lib/python2.5/pickle.py", line 1133, in load_reduce
        value = func(*args)
    TypeError: 'str' object is not callable
    

    这个 variant产生与调用基本相同的东西 r2e 本身:

    Traceback (most recent call last):
      File "./r2e-rescue.py", line 10, in <module>
        feeds = pickle.load(feedfile)
    TypeError: ("'str' object is not callable", 'sxOYAAuyzSx0WqN3BVPjE+6pgPU', ((2009, 3, 19, 1, 19, 31, 3, 78, 0), {}))
    

    编辑2

    按照J.F.Sebastian关于“printf”的建议 Feed.__setstate__ 在我的测试脚本中,以下是 Python退出之前的最后几行。

              u'http:/com/news.ars/post/20080924-everyone-declares-victory-in-smutfree-wireless-broadband-test.html': u'http:/com/news.ars/post/20080924-everyone-declares-victory-in-smutfree-wireless-broadband-test.html'},
     'to': None,
     'url': 'http://arstechnica.com/'}
    Traceback (most recent call last):
      File "./r2e-rescue.py", line 23, in ?
        feeds = pickle.load(feedfile)
    TypeError: ("'str' object is not callable", 'sxOYAAuyzSx0WqN3BVPjE+6pgPU', ((2009, 3, 19, 1, 19, 31, 3, 78, 0), {}))
    

    4 回复  |  直到 15 年前
        1
  •  5
  •   HoldOffHunger mevers303    4 年前

    我是如何解决我的问题的

    pickle.py

    以下是J.F.塞巴斯蒂安关于 pickle 格式是,我去了港口的一部分 泡菜 数据,但我觉得黑客的价值和学习更多的机会 关于Python是值得的。另外,我还是感觉好多了

    大部分移植工作(简单类型、元组、列表、字典) 到目前为止,类和对象是唯一一个需要更多关注的问题 而不仅仅是简单的习语翻译。结果是一个模块 Pickle::Parse 经过一点磨光后就可以了 在CPAN上发表。

    Python::Serialise::Pickle 发现它缺少解析功能:它会输出所有调试输出

    解析、转换数据、检测流中的实际错误

    基于 ,我试图解析 feeds.dat 文件 在修复了我解析代码中的一些小错误之后,我得到了 非常类似于的错误消息 原版

    Can't use string ("sxOYAAuyzSx0WqN3BVPjE+6pgPU") as a subroutine
    ref while "strict refs" in use at lib/Pickle/Parse.pm line 489,
    <STDIN> line 187102.
    

    哈现在我们已经到了一个非常有可能实际数据 小溪断流了。另外,我们有了一个想法 它坏了。

    结果证明,以下序列的第一行是错误的:

    g7724
    ((I2009
    I3
    I19
    I1
    I19
    I31
    I3
    I78
    I0
    t(dtRp62457
    

    "sxOYAAuyzSx0WqN3BVPjE+6pgPU" . 根据本世纪早期的类似记录 很明显,一条小溪 time.struct_time 相反所有后来的记录都共享了这个错误的指针。用一个简单的 搜索/替换操作,修复此问题很简单。

    通过Perl的特性告诉用户它在输入中的位置 当数据流消亡时。

    结论

    1. 我要离开这里 rss2email 只要我有时间 自动将其pickle配置/状态转换为
    2. 泡菜 需要更多有意义的错误消息来告诉用户 关于数据流的位置(而不是数据流本身的位置) 代码)哪里出了问题。
    3. 泡菜 对Perl来说是有趣的,并且最终是值得的。
        2
  •  3
  •   Peter Gibson    15 年前

    您是否尝试过使用cPickle和pickle手动加载feeds.dat文件?如果输出不同,则可能提示错误。

    import cPickle, pickle
    f = open('.rss2email/feeds.dat', 'r')
    obj1 = cPickle.load(f)
    obj2 = pickle.load(f)
    

    (如果rss2email没有以ascii格式pickle,您可能需要以二进制模式“rb”打开)。

    编辑:cPickle和pickle给出相同错误的事实表明feeds.dat文件是问题所在。可能是rss2email版本之间的提要类发生了变化,正如Ubuntu bug J.F.Sebastian链接中所建议的那样。

        3
  •  2
  •   Ned Batchelder    15 年前
        4
  •  2
  •   jfs    15 年前
    1. 'sxOYAAuyzSx0WqN3BVPjE+6pgPU' 很可能与泡菜的问题无关
    2. 发布错误回溯(以确定哪个类定义了无法调用的属性(导致TypeError的属性)):

      python -c "import pickle; pickle.load(open('feeds.dat'))"
      

    在代码中添加以下内容并运行(将stderr重定向到文件,然后使用 'tail -2' 在其上打印最后2行):

    from pprint import pprint
    def setstate(self, dict_):
        pprint(dict_, stream=sys.stderr, depth=None)
        self.__dict__.update(dict_)
    Feed.__setstate__ = setstate
    

    证实 'feeds.dat'

    • 备份 ~/.rss2email 目录
    • 添加两个提要,添加提要直到 “feeds.dat” 大小大于当前值。运行一些测试。
    • 试试旧的“feeds.dat”
    • 在现有rss2email安装上尝试新的“feeds.dat”

    看见 r2e bails out with TypeError