Exceptions in virtual methods¶
New in version 1.1.
It is common in Qt programming to override virtual C++ methods to customize behavior, like listening for mouse events, implement drawing routines, etc.
Fortunately, all Python bindings for Qt support overriding these virtual methods naturally in your Python code:
class MyWidget(QWidget): # mouseReleaseEvent def mouseReleaseEvent(self, ev): print('mouse released at: %s' % ev.pos())
PyQt6, exceptions in virtual methods will by default call
abort(), which will crash the interpreter. All other Qt wrappers will print the
exception stacktrace and return a default value back to C++/Qt (if a return
value is required).
This might be surprising for Python users which are used to exceptions being raised at the calling point: For example, the following code will just print a stack trace without raising any exception:
class MyWidget(QWidget): def mouseReleaseEvent(self, ev): raise RuntimeError('unexpected error') w = MyWidget() QTest.mouseClick(w, QtCore.Qt.LeftButton)
To make testing Qt code less surprising,
installs an exception hook which captures errors and fails tests when exceptions
are raised inside virtual methods, like this:
E Failed: Qt exceptions in virtual methods: E ________________________________________________________________________________ E File "x:\pytest-qt\pytestqt\_tests\test_exceptions.py", line 14, in event E raise RuntimeError('unexpected error') E E RuntimeError: unexpected error
Disabling the automatic exception hook¶
You can disable the automatic exception hook on individual tests by using a
@pytest.mark.qt_no_exception_capture def test_buttons(qtbot): ...
Or even disable it for your entire project in your
[pytest] qt_no_exception_capture = 1
This might be desirable if you plan to install a custom exception hook.
PyQt5.5, exceptions raised during virtual methods will
actually trigger an
abort(), crashing the Python interpreter. For this
reason, disabling exception capture in
PyQt6 is not
recommended unless you install your own exception hook.