2

PySide を使用して、Web ページの読み込みとスクリーンショットの作成を自動化するアプリケーションを作成しています (いいえ、既存のソリューションのいずれも使用できません)。アプリの一部は URL のリストを取得し、新しいQWebPage オブジェクトを使用して各 URL を順番に読み込みます。ページが読み込まれた後、スクリーンショットが撮影され、QWebPage オブジェクトが削除されます。

時々、十分な数の実行があると、RuntimeError 例外として PySide から次のエラーが発生します。

Invalid Signal signature: loadStarted()
Failed to connect signal loadStarted().

最初の行は (おそらく Qt によって) STDERR に出力され、2 行目は Python の例外です。

loadStarted() は組み込みの QWebPage シグナルであり、私が作成したものではありません。これは 90% の確率で機能しますが、時折失敗する原因がわかりませんでした。

正直なところ、このアプリは、PySide/Qt を uWSGI で提供される Web アプリにフックするため、設計上非常に珍しいものです。これは、たとえば、QApplication イベント ループを使用するのではなく、ページの読み込みごとにローカル イベント ループを使用していることを意味します。私は Qt も Python も経験がないので、多くの間違いを犯している可能性がありますが、それらが何であるかわかりません。

この投稿が何か関係があるのではないかと思いますが、よくわかりません。

次にどこを見るべきかについての提案はありますか?

更新:信号は次のコードを介して接続されます。

class MyWebPage(QWebPage):

    def __init__(self, parent=None):
        super(MyWebPage, self).__init__(parent)
        self.loadStarted.connect(self.started)
        self.loadFinished[bool].connect(self.finished)

MyWebPage オブジェクトは、プロセスがシャットダウンするまで削除されない別の単一の QObject インスタンスの子として作成されます。それらは、処理が完了したら page.deleteLater() を呼び出すことによって削除されます。私はローカル イベント ループを実行しているので、ローカル イベント ループを終了した後、次のように呼び出して遅延削除をトリガーします。

 # self.eventLoop is the local event loop, which at this stage is not running
 self.eventLoop.processEvents()

 # self.app is the QApplication instance
 self.app.sendPostedEvents(None, QEvent.DeferredDelete)
4

2 に答える 2

0

私は同じ問題を抱えていました (これらのエラーは時々発生しますが、一貫して再現することはできませんでした)。シグナルをそれらに接続しようとすると、存在しないメソッドと関係があるというのは正しいと思います-それをテストするために、.connect 呼び出しを別のメソッドに入れると、エラーはなくなりました。例えば:

編集: (数時間後) 話すのが早すぎたようです。またエラーが発生しました。

更新: (数週間後)

私は構文をいろいろいじり、時折、RuntimeError が発生することさえありました (おそらくPySide のこのバグ?)。理由はまだ完全にはわかりませんが、エラーが一貫して発生しないため、おそらく次のように強制しても安全です。

class MyWebPage(QWebPage):

def __init__(self, parent=None):
    super(MyWebPage, self).__init__(parent)

    success = False
    while not success:
        try:
            success = self.loadStarted.connect(self.started)
        except RuntimeError:
            success = False

    success = False
    while not success:
        try:
            success = self.loadFinished[bool].connect(self.finished)
        except RuntimeError:
            success = False

本当に安全にしたい場合は、ループカウンターを保持して、信号がしきい値の前に正しく接続されない場合にプログラムをクラッシュさせることができます。

于 2012-07-03T20:38:21.873 に答える