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

标签 python rss pickle

我正在使用 rss2email 将大量 RSS 提要转换为邮件以便于使用。也就是说,我正在使用它是因为它今天以一种可怕的方式崩溃:在每次运行中,它只给我这个回溯:

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 将其转储。

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

为了重建文件,我可以尝试哪些方法?

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

编辑

Peter Gibson 和 J.F. 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)

“普通”pickle 变体产生以下回溯:

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

cPickle 变体产生与调用基本相同的东西 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 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 机器上。

最佳答案

我是如何解决我的问题的

pickle.py 的 Perl 端口

根据 J.F. Sebastian 关于 pickle 多么简单的评论 格式是,我出去将 pickle.py 的部分移植到 Perl。一对夫妇 的快速正则表达式本来是一种更快的方式来访问我的 数据,但我觉得黑客的值(value)和学习更多的机会 关于 Python 是值得的。另外,我还有更多的感觉 Perl 的使用(和调试代码)比 Python 更舒服。

大部分移植工作(简单类型、元组、列表、字典) 很直接。 Perl 和 Python 的不同概念 到目前为止,类和对象是唯一的问题 而不是简单的成语翻译。结果是一个模块 称为 Pickle::Parse ,经过一些抛光后将是 发表在 CPAN 上。

CPAN 上存在一个名为 Python::Serialise::Pickle 的模块,但我 发现它缺乏解析能力:它会吐出所有的调试输出 在这个地方,似乎不支持类/对象。

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

基于 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,
<STDIN> line 187102.

哈!现在我们所处的位置很可能是实际数据 流坏了。另外,我们知道它在哪里坏了。

原来是下面这个序列的第一行是错误的:

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

“备忘录”中的位置7724指向该字符串 “sxOYAAuyzSx0WqN3BVPjE+6pgPU”。从早期的类似记录 流,显然需要一个 time.struct_time 对象 反而。所有后来的记录都共享这个错误的指针。用一个简单的 搜索/替换操作,解决这个问题很简单。

我觉得很讽刺,我偶然发现了错误的来源 通过 Perl 的功能告诉用户它在输入中的位置 死亡时的数据流。

结论

  1. 一有时间我就会离开 rss2email 自动将其 pickle 的配置/状态困惑转换为 另一种工具的格式。
  2. pickle.py 需要更有意义的错误消息来告诉用户 关于数据流的位置(不是它自己的位置 代码)出问题的地方。
  3. 将部分 pickle.py 移植到 Perl 很有趣,而且最终收获颇丰。

关于python - 如何恢复损坏的 python "cPickle"转储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/664444/

相关文章:

python - Tastypie - 找不到嵌套资源字段

java - 围绕 java 类传递数据

java - 如何点击 jsonobject/listview 提要项?

python - 在类内部创建类的副本

python - Google App Engine 边缘缓存不工作

python - 可空列的 Django REST ViewSet 排序

python 3.6 socket pickle 数据被截断

Python:修改 pickle 对象

python - Ubuntu 16.04 python 安装第 3 方模块 ffmpeg-3.0.2

rss - 如何使用 SyndicateFeed 和 ServiceStack 改进我的 Rss/Atom 解决方案?