# Exceptions in virtual methods

New in version 1.1.

Note

`PySide6 6.5.2+` automatically captures exceptions that happen during the Qt event loop and re-raises them when control is moved back to Python, so the functionality described here does not work with `PySide6` (nor is necessary).

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(f"mouse released at: {ev.pos()}")

In `PyQt5` and `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, `pytest-qt` automatically 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 `qt_no_exception_capture` marker:

    @pytest.mark.qt_no_exception_capture
    def test_buttons(qtbot):
        ...

Or even disable it for your entire project in your `pytest.ini` file:

    [pytest]
    qt_no_exception_capture = 1

This might be desirable if you plan to install a custom exception hook.

Note

Starting with `PyQt5.5`, exceptions raised during virtual methods will actually trigger an `abort()`, crashing the Python interpreter. For this reason, disabling exception capture in `PyQt5.5+` and `PyQt6` is not recommended unless you install your own exception hook.

Note

As explained in the note at the top of the page, `PySide6 6.5.2+` has its own exception capture mechanism, so this option has no effect when using this library.