7

問題を示すコードは次のとおりです。

from PyQt4 import QtGui
app = QtGui.QApplication([])
dialog = QtGui.QDialog()
button = QtGui.QPushButton('I crash')
layout = QtGui.QHBoxLayout()
layout.addWidget(button)
dialog.setLayout(layout)
def crash(): raise Exception('Crash!')
button.clicked.connect(crash)
button.click()
print 'I should not happen'

それを実行すると、PyQt4 がエラーを処理してくれます。コンソールに「Crash!」というスタック トレースが表示される などで、「私は起こるべきではない」とわかります。

多くのハンドラーを持つ大規模なアプリケーションを渡されたので、これは役に立ちません。すべてのエラーを自分の顔に (そして、私の - エヘム - 自動テストに) 強制する必要があります。実行するたびに、エラーがネットから逃れ、すべてのエラーをキャッチするために、すべてのハンドラー内で過剰で役に立たない try:except ブロックが必要になります。

別の言い方をすれば、良いコードは非常に良いものであり、悪いコードは非常に悪いものであってほしいということです。白塗りではありません。

これがすでに尋ねられている場合は申し訳ありませんが、電子検索すると、何千人もの初心者が基本的なエラー処理の質問をするのは自然なことです (さらに悪いことに、わがままな例外をオフにする方法を尋ねる初心者もいます!;)

PyQt4 のデフォルトのエラー処理をオーバーライドして、自分でエラーを伝播または記録するにはどうすればよいですか? また、sys.excepthook にも回答しないでください。PyQt4 がキャッチしないエラーをキャッチします。

4

2 に答える 2

2

答えは、これはの「機能」PyQtではなく、信号/スロットを機能させる設計に固有の結果であると思います(信号/スロット通信もc ++層を経由することを忘れないでください)。

これは醜いですが、あなたの問題を少し回避します

from PyQt4 import QtGui
import time
app = QtGui.QApplication([])

class exception_munger(object):
    def __init__(self):
        self.flag = True
        self.txt = ''
        self.type = None

    def indicate_fail(self,etype=None, txt=None):
        self.flag = False
        if txt is not None:
            self.txt = txt
        self.type = etype
    def reset(self):

        tmp_txt = self.txt
        tmp_type = self.type
        tmp_flag = self.flag
        self.flag = True
        self.txt = ''
        self.type = None
        return tmp_flag, tmp_type, tmp_txt

class e_manager():
    def __init__(self):
        self.old_hook = None

    def __enter__(self):
        em = exception_munger()
        def my_hook(type, value, tback):
            em.indicate_fail(type, value)
            sys.__excepthook__(type, value, tback) 
        self.old_hook = sys.excepthook
        sys.excepthook = my_hook
        self.em = em
        return self

    def __exit__(self,*args,**kwargs):
        sys.excepthook = self.old_hook

def mang_fac():
    return e_manager()

def assert_dec(original_fun):

    def new_fun(*args,**kwargs):
        with mang_fac() as mf:
            res = original_fun(*args, **kwargs)
            flag, etype, txt = mf.em.reset()
            if not flag:
                raise etype(txt)
            return res
    return new_fun


@assert_dec
def my_test_fun():
    dialog = QtGui.QDialog()
    button = QtGui.QPushButton('I crash')
    layout = QtGui.QHBoxLayout()
    layout.addWidget(button)
    dialog.setLayout(layout)
    def crash(): 
        time.sleep(1)
        raise Exception('Crash!')
    button.clicked.connect(crash)


    button.click()

my_test_fun()
print 'should not happen'

これは「発生しないはずです」と出力せず、自動テストでキャッチするものを提供します(正しい例外タイプを使用)。

In [11]: Traceback (most recent call last):
  File "/tmp/ipython2-3426rwB.py", line 68, in crash
Exception: Crash!
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-11-6ef4090ab3de> in <module>()
----> 1 execfile(r'/tmp/ipython2-3426rwB.py') # PYTHON-MODE

/tmp/ipython2-3426rwB.py in <module>()

/tmp/ipython2-3426rwB.py in new_fun(*args, **kwargs)

Exception: Crash!

In [12]: 

スタックトレースはジャッキアップされていますが、印刷された最初のトレースを読み取ることができます。

于 2013-01-24T05:26:40.000 に答える