PyQt: No error msg (traceback) on exit

Question:

My PyQt application no longer prints the error (stderr?) to the console.

I use QtDesigner and import the UI like this:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.uic import loadUiType
Ui_MainWindow, QMainWindow = loadUiType("test.ui")

class Main(QMainWindow, Ui_MainWindow):
    """Main window"""
    def __init__(self,parent=None):
        super(Main, self).__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.testfunc)

   def testfunc(self):
        print(9/0)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main = Main()
    main.show()
    sys.exit(app.exec_())

test.ui contains a QPushButton and a label. When I call testfunc (which obviously gives an error) in a non-Qt application, I get the error message, traceback, etc. When I execute this code, it just exits.

I wrote a PyQt application without QtDesigner before and it printed the errors to the console as expected. What’s the difference with QtDesigner and inheritance?

Asked By: Jannis

||

Answers:

This is probably due to changes in the way exceptions are dealt with in PyQt-5.5. To quote from the PyQt5 Docs:

In PyQt v5.5 an unhandled Python exception will result in a call to
Qt’s qFatal() function. By default this will call abort() and the
application will terminate. Note that an application installed
exception hook will still take precedence.

When I run your example in a normal console, this is what I see:

$ python test.py
Traceback (most recent call last):
  File "test.py", line 213, in testfunc
    print(9/0)
ZeroDivisionError: division by zero
Aborted (core dumped)

So the main difference is that the application will now immediately abort when encountering an unhandled exception (i.e. just like a normal python script would). Of course, you can still control this behaviour by using a try/except block or globally by overriding sys.excepthook.

If you’re not seeing any traceback, this may be due to an issue with the Python IDE you’re using to run your application.

PS:

As a bare minimum, the old PyQt4 behaviour of simply printing the traceback to stdout/stderr can be restored like this:

def except_hook(cls, exception, traceback):
    sys.__excepthook__(cls, exception, traceback)

if __name__ == "__main__":

    import sys
    sys.excepthook = except_hook
Answered By: ekhumoro

I’ve been using python’s traceback module in conjunction with a try/except statement to make sure the traceback is printed before exiting:
https://docs.python.org/3/library/traceback.html

Spefically, I use traceback.print_exc()

Answered By: Luis Vidal