Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to debug PyQt applications without relaunching?

Tags:

python

qt

pyqt

I use Qt + PyQt for developing. My application is very-very big (20 MB of source code). It includes many different menus and widgets. Very oftne I change only 1 string on method in some widget. But for checking changes I switch off my application, relaunch it, go to menu1 -> menu2 …. and only after this step I can check changes.

How can I reload methods for only one class/widget? Without close/open whole application?

like image 574
SkyFox Avatar asked Mar 12 '12 11:03

SkyFox


1 Answers

My general reply to this would be no, its not possible in a straight-forward fashion. The main issue is that when you start your app, it loads everything into memory, and your classes have their methods bound, etc... So in order to update say, values you changed of a method of a class, you would have to destroy that class (or widget) and recreate it under the updated source (which would also kill the children).

Its bad looking, but it would look something like this:

## main.py ##

class MainWindow(QtGui.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.resize(640,480)
        self.central = widget.Widget()
        self.setCentralWidget(self.central)

        self.toolbar = QtGui.QToolBar()
        self.toolbar.addAction("Reload Entire Widget", self._reloadWidget)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar)

    def _reloadWidget(self):
        print "Reloading", widget
        reload(widget)
        self.central.deleteLater()
        self.central = widget.Widget()
        self.setCentralWidget(self.central)

## widget.py ##

class Widget(QtGui.QWidget):

    def __init__(self, *args, **kwargs):
        super(Widget, self).__init__(*args, **kwargs)
        self.layout = QtGui.QVBoxLayout(self)
        self.button = QtGui.QPushButton("Click")
        self.layout.addWidget(self.button)

        self.button.clicked.connect(self.testMethod)

    def testMethod(self):
        print "testmethod(): FOO"

Again, I think this approach is problematic and difficult to deal with since you have to destroy and recreate your widget. More problems occur when parts of your app have signals bound to slots of this widget being updated. You then also have to reload their modules and relink their signals. It becomes a big dependency tree situation. Its hard enough to do with standard python script, let alone trying to do it with something much more persistant and dynamic like the PyQt framework.

Basically, don't rely on this ability. You are better off maybe setting up something with QTest to simulate your repetitive tasks.

like image 82
jdi Avatar answered Oct 31 '22 19:10

jdi