3

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.datrss2email保持するファイルが何らかの形で壊れているということです。どうやら、rss2emailその状態を読み取り、実行ごとに使用してダンプしcPickleます。

巨大な (>12MB)ファイル'sxOYAAuyzSx0WqN3BVPjE+6pgPU'で、上記の文字列を含む行を見つけました。feeds.dat私の訓練されていない目には、ダンプが切り捨てられたり、破損したりしているようには見えません。

ファイルを再構築するためにどのようなアプローチを試すことができますか?

Python のバージョンは、Debian/不安定なシステムでは 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)

「プレーンな」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

私のテスト スクリプトに「printf デバッグ」を入れることに関する JF Sebastian の提案に従って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 ボックスでも同じことが起こります。

4

4 に答える 4

6

問題をどのように解決したか

のPerlポートpickle.py

フォーマットがいかに単純であるかについてのJFSebastianのコメントに続いて、私はPerlpickle への移植部分に出かけました。pickle.pyいくつかの簡単な正規表現が私のデータにアクセスするためのより速い方法でしたが、ハックの価値とPythonについてもっと学ぶ機会はそれだけの価値があると感じました。さらに、PythonよりもPerlの使用(およびコードのデバッグ)の方がはるかに快適だと感じています。

移植作業のほとんど(単純なタイプ、タプル、リスト、辞書)は非常に簡単でした。PerlとPythonのクラスとオブジェクトの異なる概念は、これまでのところ、イディオムの単純な翻訳以上のものが必要とされた唯一の問題でした。その結果、モジュールが呼び出さPickle::Parseれ、少し磨いた後、CPANで公開されます。

と呼ばれるモジュールPython::Serialise::PickleがCPANに存在しましたが、その解析機能が不足していることがわかりました。デバッグ出力をいたるところに吐き出し、クラス/オブジェクトをサポートしていないようです。

データの解析、変換、ストリーム内の実際のエラーの検出

に基づいてPickle::Parsefeeds.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ピクルス化された構成/状態の混乱を別のツールの形式に自動的に変換する時間ができたらすぐに離れます。
  2. pickle.py問題が発生したデータストリームの位置(独自のコード内の位置ではない)をユーザーに通知する、より意味のあるエラーメッセージが必要です。
  3. パーツpickle.pyをPerlに移植するのは楽しかったし、結局はやりがいがありました。
于 2009-04-05T18:49:16.087 に答える
3

cPickle と pickle の両方を使用して、feeds.dat ファイルを手動でロードしようとしましたか? 出力が異なる場合は、エラーを示唆している可能性があります。

次のようなもの(ホームディレクトリから):

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

(rss2email が ascii でピクルしない場合は、バイナリ モード 'rb' で開く必要があるかもしれません)。

ピート

編集: cPickle と pickle で同じエラーが発生するという事実は、feeds.dat ファイルに問題があることを示唆しています。JF Sebastian がリンクしている Ubuntu のバグで示唆されているように、おそらく rss2email のバージョン間の Feed クラスの変更です。

于 2009-03-20T00:40:19.880 に答える
2

cPickle の内部が絡み合っているようです。このスレッド ( http://bytes.com/groups/python/565085-cpickle-problems ) には手がかりがあるようです..

于 2009-03-20T00:46:26.030 に答える
2
  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ディレクトリ
  • rss2email を virtualenv/pip サンドボックスにインストール (または zc.buildout を使用) して、環境を分離します (トランクから feedparser.py を使用していることを確認してください)。
  • いくつかのフィードを追加し、'feeds.dat'サイズが現在よりも大きくなるまでフィードを追加します。いくつかのテストを実行します。
  • 古い「feeds.dat」を試してください
  • 既存の rss2email インストールで新しい「feeds.dat」を試してください

r2eが Ubuntu の TypeError バグで救済されるのを参照してください。

于 2009-03-20T01:01:15.977 に答える