Multiple instances of QApplication in one process

I’m working on a PyQt 4 application for my employer Chess. Of course I’m writing plenty of unit tests for it as well. Those tests have to be cleanly separated from each other, so every test that requires the entire application to be up and running should have its own instance. And this is where it gets tricky, as Qt (and thus PyQt) assumes that there will only be one application, and if that application quits the process quits.

In my unit tests, this is not the case. Every test can potentially start and stop an application, and the test suite will continue running. This caused a segmentation fault (a.k.a. segfault) the second time the QApplication closed.

After a lot of puzzling I found out that QtGui.qApp needs to refer to the running QApplication instance, and be set to None when the application has been closed. After I implemented this the segfaults went away.

This is my ApplicationTest mix-in class that I use for controlling my application lifespan. It contains a little trick to stop the application as soon as it has started:

class MyApplicationClass(QtGui.QApplication):

  started = QtCore.pyqtSignal()

  def exec_(self):
      self.started.emit()
      return QtGui.QApplication.exec_()

class _ApplicationTest(object):
  '''Mix-in class that can start and stop an application.'''

  APP_CLASS = MyApplicationClass

  def __init__(self):
      self.app = None
      QtGui.qApp = None

  def create_app(self):
      '''Creates and returns a new application'''

      self.app = self.APP_CLASS([])
      QtGui.qApp = self.app
      return self.app

  def stop_app(self):
      '''Stops the application.'''

      if not self.app: return

      self.app.started.connect(self.app.quit,
              type=QtCore.Qt.QueuedConnection)
      self.app.exec_()

      QtGui.qApp = None
      self.app = None
dr. Sybren A. Stüvel
dr. Sybren A. Stüvel
Open Source software developer, photographer, drummer, and electronics tinkerer

Related