当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何恢复损坏的python"cPickle"转储?》经验,为你挑选了1个好方法。

rss2email用于将大量RSS源转换为邮件以便于使用.也就是说,我使用它,因为它在一个可怕的方式打破了今天:在每次运行时,它只是给了我这个回溯:

Traceback (most recent call last):
  File "/usr/share/rss2email/rss2email.py", line 740, in 
    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.datrss2email某种方式被破坏.显然,rss2email读取其状态并cPickle在每次运行时将其转储回来.

我甚'sxOYAAuyzSx0WqN3BVPjE+6pgPU'至在巨型(> 12MB)feeds.dat文件中找到了包含上述字符串的行.对于我未经训练的眼睛,转储似乎没有被截断或以其他方式损坏.

我可以尝试哪些方法来重建文件?

在Debian/unstable系统上,Python版本是2.5.4.

编辑

Peter Gibson和JF Sebastian建议直接从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 
    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

cPickle变种实质上产生同样的事情,调用 r2e本身:

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

编辑2

在JF Sebastian建议将"printf debugging"放入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), {}))

在使用python 2.4.4-2的Debian/etch盒子上也会发生同样的事情.



1> hillu..:
我是如何解决我的问题的

一个Perl端口 pickle.py

在JF Sebastian关于pickle 格式有多简单的评论之后,我出去将部分内容移植pickle.py到Perl.一些快速正则表达式可以更快地访问我的数据,但我觉得黑客价值和了解Python的更多机会是值得的.另外,我仍然觉得使用Perl比使用Python(和调试代码)更舒服.

大多数移植工作(简单类型,元组,列表,字典)都非常简单.到目前为止,Perl和Python的类和对象的不同概念是唯一的问题,需要的不仅仅是简单的习语翻译.结果是一个模块被称为Pickle::Parse经过一些抛光后将在CPAN上发布.

一个名为Python::Serialise::PickleCPAN的模块存在,但我发现它的解析功能缺乏:它在整个地方调试输出并且似乎不支持类/对象.

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

基于此Pickle::Parse,我试图解析该feeds.dat文件.经过几次修复我的解析代码中的琐碎错误之后,我得到了一条错误消息,它与pickle.py原始 对象无法调用的错误消息非常相似:

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

哈!现在我们正处于实际数据流很可能被破坏的程度.另外,我们知道哪里坏了.

事实证明,以下序列的第一行是错误的:

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

"备忘录"中的位置7724指向该字符串 "sxOYAAuyzSx0WqN3BVPjE+6pgPU".从流中较早的类似记录中可以看出,time.struct_time需要一个对象.所有后来的记录共享这个错误的指针 通过简单的搜索/替换操作,解决这个问题是微不足道的.

我发现具有讽刺意味的是,我通过Perl的功能偶然发现了错误的来源,该功能告诉用户它在输入数据流中的位置.

结论

    rss2email一旦我有时间自动将其酸洗配置/状态混乱转换为其他工具的格式,我就会离开.

    pickle.py 需要更有意义的错误消息,告诉用户数据流的位置(而不是自己代码中的poision)出错的地方.

    将部件移植pickle.py到Perl很有趣,最后也是有益的.

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有