18

I'm doing some very simple PySide (and PyQt) tutorials in IPython. One tutorial just creates a window with some sliders to demonstrate slots and signals.

When I close the window of the running demo application, I see this error:

An exception has occurred, use %tb to see the full traceback.
SystemExit: 0
To exit: use 'exit', 'quit', or Ctrl-D.

So I run %tb and get this:

SystemExit                                Traceback (most recent call last)
/Workspaces/scratch/<ipython-input-1-88966dcfb499> in <module>()
     33 
     34 if __name__ == "__main__":
---> 35     main()

/Workspaces/scratch/<ipython-input-1-88966dcfb499> in main()
     29         w.show()
     30         app.exec_()
---> 31         sys.exit(0)
     32 
     33 

SystemExit: 0

If I try to execute my code again, I get this:

RuntimeError: A QApplication instance already exists.

In case it helps, here my code:

from PySide.QtCore import *
from PySide.QtGui import *
import sys

class MyWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self, None)

        vbox = QVBoxLayout(self)

        self.slider1 = QSlider(Qt.Horizontal)
        self.slider1.setRange(0, 99)
        self.slider1.setValue(0)
        vbox.addWidget(self.slider1)

        self.slider2 = QSlider(Qt.Horizontal)
        self.slider2.setRange(0, 99)
        self.slider2.setValue(99)
        vbox.addWidget(self.slider2)

        self.slider1.valueChanged.connect(self.slider2Changed)

    def slider2Changed(self, position):
        self.slider2.setValue(self.slider2.maximum() - position)

def main():
        app = QApplication(sys.argv)
        w = MyWindow()
        w.show()
        app.exec_()
        sys.exit(0)

if __name__ == "__main__":
    main()

I do not have errors when running the code using python:

python myexample.py

This error only happens when I run the code in an IPython (including a notebook or the qtconsole or the regular ipython terminal).

UPDATE: My main problem is that I cannot run the application again quickly and easily. If I try to run my code again, I get this:

RuntimeError: A QApplication instance already exists.

That kills the fast, interactive nature of IPython :(

minrk
  • 37,545
  • 9
  • 92
  • 87
MountainX
  • 6,217
  • 8
  • 52
  • 83

5 Answers5

28

This answer is thanks to Matthias BUSSONNIER from the ipython-users mailing list.

When I close the window of the running demo application, I see this error: An exception has occurred, use %tb to see the full traceback. SystemExit: 0

Just don't use sys.exit(0) as you are not exiting python, but still running IPython.

Add it back if you wish to run your app from a (real) command line and have a return status.

If I try to execute my code again, I get this:
RuntimeError: A QApplication instance already exists.

This is a PySide Bug that they "won't fix" as they don't consider it a bug.

See https://github.com/ipython/ipython/issues/1124)
and http://bugs.pyside.org/show_bug.cgi?id=855

QApplication can only have one instance and quitting an app is apparently not considered a reason sufficient enough do delete the object...

You can use this code from above issues :

app=QtGui.QApplication.instance() # checks if QApplication already exists 
if not app: # create QApplication if it doesnt exist 
     app = QtGui.QApplication(sys.argv)

This was a sufficient solution for my present needs.

MountainX
  • 6,217
  • 8
  • 52
  • 83
  • Thanks for the code for solving this issue. I've had this problem for a long time. – Jabba Dec 11 '12 at 20:29
  • Thank you for the QApplication.instance() tip. I never knew it had this method. Now I can, hopefully, implement application single-instance checking in my app. :) – Boštjan Mejak Jul 13 '19 at 22:31
10

What you need to do is to cause the QApplication to be deleted later as in:

app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)

Using this code you can rerun the application as many times as you want in IPython, or anywhere else and every time you close your qt application, the object will be deleted in python.

Ali B
  • 491
  • 1
  • 5
  • 14
5

sys.exit just raises SystemExit to terminate the interperter.

ipython catches SysExit when it executes a script in interactive mode, so this isn't acutally an error but a feature of ipython do avoid the interactive interpreter from being shutdown when a script is executed, as that's not what you usually want in an interactive session.

mata
  • 67,110
  • 10
  • 163
  • 162
  • OK. How do I solve the issue that I am unable to run the application again after closing it once? I have to restart the iPython kernel before I can execute my app again. Otherwise, I get this: `RuntimeError: A QApplication instance already exists.` – MountainX Jun 04 '12 at 22:10
  • That has to do with Qt. You can't have two QApplications running at the same time. The safest way _is_ to restart the interpreter. I've only tried it with PyQt4 and with that it seems to work if I delete all references to the old QApplication before creating a new one. But usually you're not supposed to start another QApplication in the same process. – mata Jun 04 '12 at 22:28
  • 1
    Well, when I close my application, I don't expect the interpreter to keep it running or to keep references to it. So something is broken. Restarting the kernel is not a good solution because it kills iPython's productivity. – MountainX Jun 04 '12 at 23:07
5

According to https://github.com/spyder-ide/spyder/issues/4639,

First, check if the instance is already present, and either assign that, or make a new one:

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

(This snippet is taken from the answer by @NotSoBrainy.)

Then, after the show() method:

QtWidgets.QApplication.setQuitOnLastWindowClosed(True)
app.exec_()
app.quit()

There’s no need for sys.exit().

This solved my issue, which was exactly the same.

Parthesh Soni
  • 133
  • 1
  • 6
  • 1
    This is essentially the same answer as @NotSoBrainy gave last year. Since you provide additional details and a reference, it’s a useful contribution. But it’s worth acknowledging similarities and differences when posting new answers to old questions. – Jeremy Caney May 25 '20 at 16:59
  • Ok, got it. Actually I got this from the link provided in my answer. Anyways, I will give acknowledgement. – Parthesh Soni May 26 '20 at 03:50
1

Check if already an instance of QApplication is present or not as the error occurs when an instance is already running and you are trying to create a new one.

if not QtWidgets.QApplication.instance():
    app = QtWidgets.QApplication(sys.argv)
else:
    app = QtWidgets.QApplication.instance()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
NotSoBrainy
  • 63
  • 10