felixg
felixg

Reputation: 23

Debug QT5 application in Spyder3

I am desperately trying to use the Spyder3 built-in debugger to debug a pyqt5 application. It seems that as soon as the qt app is running the breakpoints are not hit anymore. I had a similar problem with exceptions occurring inside slots which somehow by default are lost along their way to the console. For that there is a workaround which works most of the time. However, debugging seems quite impossible.

The code which should demonstrate the problem:

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow

import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(240, 190, 75, 23))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.pushButton.clicked.connect(MainWindow.clicked_slot)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))

class main_app_class(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.show()

    def clicked_slot(self):
        """Breakpoints in here are never hit"""
        print("Hit me!")

if __name__ == "__main__":
    if not QApplication.instance():
        app = QApplication(sys.argv)
    else:
        app = QApplication.instance() 

    main_app = main_app_class()
    main_app.show()

    app.exec_()

Thanks a lot for any help or hint,

Felix

Upvotes: 2

Views: 1187

Answers (1)

Carlos Cordoba
Carlos Cordoba

Reputation: 34136

(Spyder maintainer here) There are two things you need to do to enter debugging with Spyder in a PyQt slot:

  1. Make graphical applications to block the console while they are running. For that you need to go to

    Tools > Preferences > IPython Console > Graphics

    and deactivate the option called Activate support.

  2. You need to modify your clicked_slot method like this

    def clicked_slot(self):
        import pdb; pdb.set_trace()
        print("Hit me!")
    

    The statement import pdb; pdb.set_trace() is a programmatic way to enter debugging. So, as soon as Python encounters that instruction, it'll enter debugging automatically. And that happens, in your case, when you press the Push button

  3. You need to run (and not debug) your application with F5 or Run > Run.


Note: There are two important limitations of this approach:

  1. Your application will freeze as soon as you enter debugging. So you won't be able to further interact with it.
  2. The only way to exit debugging is by closing the window created by your app.

Upvotes: 2

Related Questions