Spyder: PyQt code cannot run twice

Created on 8 Feb 2016  路  27Comments  路  Source: spyder-ide/spyder

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    sys.exit(app.exec_())  

i can not run the code twice it says kernel stopped.but in other ide's it runs smoothly again and again in web there are other ppl mention about this please fix this bug
http://stackoverflow.com/questions/19459299/running-a-pyqt-application-twice-from-one-prompt-in-spyder
http://stackoverflow.com/questions/33527108/pyqt-examples-not-running-second-time

this bug is general it covers all spyder versions i think ,i tried a few but in all , kernel crashes

IPython Console Bug v4.1.0

Most helpful comment

based on @eendebakpt 's code, the following workaround works for me on windows/anaconda 4.4.0/python 3.6:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *


if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    else:
        print('QApplication instance already exists: %s' % str(app))

    window = QtWidgets.QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    app.exec_()

can't say anything about other platforms currently

All 27 comments

Yes, this is a known issue and we don't know how to fix it yet.

@mvkrdndm, I would advice that you use F6 option Execute in a new dedicated Python console when running Qt Code.

image

The following code works for me. Note the check on QApplication already running and not executing the exit statement at the end.

import sys
import PyQt4.QtGui as QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *

if __name__ == '__main__':
    app = QtGui.QApplication.instance()
    if app is None:
        app = QtGui.QApplication(sys.argv)
    else:
        print('QApplication instance already exists: %s' % str(app))

    window = QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    app.exec_()

The solution provided by @eendebakp does not work for me on windows, but does on linux
Windows machine uses anaconda w/ python 3.5
Linux machine uses python 3.6 (no anaconda)

based on @eendebakpt 's code, the following workaround works for me on windows/anaconda 4.4.0/python 3.6:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *


if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    else:
        print('QApplication instance already exists: %s' % str(app))

    window = QtWidgets.QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    app.exec_()

can't say anything about other platforms currently

I get rid of it by running the program with hot key F10 (Run鈫扨rofile).

The workarounds mentioned here did not work for me, but this seems to work for me (Windows, Anaconda, Python 3.7.2, IPython 7.2.0):

app = QtWidgets.QApplication(sys.argv)
app.lastWindowClosed.connect(app.quit)
widget = QtWidgets.QDialog()
widget.show()
app.exec_()

The workarounds mentioned here did not work for me, but this seems to work for me (Windows, Anaconda, Python 3.7.2, IPython 7.2.0):

app = QtWidgets.QApplication(sys.argv)
app.lastWindowClosed.connect(app.quit)
widget = QtWidgets.QDialog()
widget.show()
app.exec_()

This works on Windows, Anaconda, Python 3.7,3, IPython 7.4.0

Manually deleting the app object works for me (Windows / Python 3.6.7 / Qt5):

app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QDialog()
widget.show()
app.exec_()
del app

The workaround of @jcnossen works also on (Debian Linux / Python 3.6.8 / Qt5.9.6 / IPython 7.5.0 / JupyterLab 0.35.5):

if 'app' in locals():
    del app

app = QtGui.QApplication([])

# CODE

if __name__ == '__main__':
    QtGui.QApplication.instance().exec_()

JupyterLab 0.35.5

I don't understand this. Are you reporting to the right place?

I did not investigate this deeper, but I think this is an issue of running Qt in IPython.
JupyterLab runs internally also an IPython kernel.
So, I am not sure, whether this is an issue of spyder at all...

Should we add some logic to check for QApplication imports and give a warning and "change the code" as needed?

We should probably not run this code as it will indeed block the console.

@impact27 do you have some ideas?

I can't reproduce by running this code:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = QtWidgets.QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    app.exec_()

So either it was fixed upstream or I am missing something.
One thing I noticed is that a python icon appears in the macOS dock that is related to the kernel. If you right click + force quit, this will quit the kernel. But this is expected as the kernel process just showed an image, macOS classifies it as a GUI app.

I can reproduce it if I run it several times. The first time it might run, the rest it wont or blocks the kernel or you get a mesaage saying an qap is already running.

I just ran the code five times in the same kernel without issue. I reinstalled python and all the packages last week.

Hmmm this is weird :-\

@dalthviz, can you reproduce this on Windows?

@ccordoba12 testing this on Windows, Python 3.7.3/Anaconda:

Code versions that work:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *


if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    else:
        print('QApplication instance already exists: %s' % str(app))

    window = QtWidgets.QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    app.exec_()

image

# Similar code to the original post but using PyQt5
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    sys.exit(app.exec_()) 

image

Code version with strange behaviors:

Running the following code from a file no issue raises but seems like the kernel is restarting when running the second time:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = QtWidgets.QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    app.exec_()

image

Also, should the wiki page we have about running PyQt applications be updated?

@dalthviz, so what's your conclusion? I mean, when do things work and when do they fail?

I can reproduce if I paste the code in the console directly. I get a segfault when creating the widget:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [26752]

VM Regions Near 0:
--> 
    __TEXT                 0000000101037000-0000000101039000 [    8K] r-x/r-x SM=COW  /usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   QtGui                           0x0000000114c30e3f QGuiApplication::font() + 127
1   QtGui                           0x0000000114ccd984 QFont::QFont() + 36
2   QtWidgets                       0x000000011576190b QWidgetPrivate::QWidgetPrivate(int) + 331
3   QtWidgets                       0x000000011576270e QWidget::QWidget(QWidget*, QFlags<Qt::WindowType>) + 46
4   QtWidgets.so                    0x000000011532116d init_type_QWidget(_sipSimpleWrapper*, _object*, _object*, _object**, _object**, _object**) + 173
5   sip.cpython-37m-darwin.so       0x0000000114866ac5 sipSimpleWrapper_init + 181

Without the widget:

In [1]: from PyQt5 import QtWidgets
   ...: app = QtWidgets.QApplication([])
   ...: app.exec_()
Out[1]: 0

In [2]: from PyQt5 import QtWidgets
   ...: app = QtWidgets.QApplication([])
   ...: app.exec_()
QApplication::exec: Please instantiate the QApplication object first
Out[2]: -1

In [3]: 

Without executing: (Crashes)

In [1]: from PyQt5 import QtWidgets
   ...: app = QtWidgets.QApplication([])
   ...: window = QtWidgets.QWidget()
   ...: window.show()

In [2]: from PyQt5 import QtWidgets
   ...: app = QtWidgets.QApplication([])
   ...: window = QtWidgets.QWidget()
   ...: window.show()

In [1]: 

Without an app: (Crashes)

In [1]: from PyQt5 import QtWidgets
   ...: window = QtWidgets.QWidget()
   ...: window.show()

In [1]: 

But I can reproduce that in qtconsole and in ipython and in python:

quentinpeter@MacBook-Pro-de-Quentin ~ % python3
Python 3.7.5 (default, Nov  1 2019, 02:16:23) 
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt5 import QtWidgets; app = QtWidgets.QApplication([]); QtWidgets.QWidget()
<PyQt5.QtWidgets.QWidget object at 0x10fc2c370>
>>> from PyQt5 import QtWidgets; app = QtWidgets.QApplication([]); QtWidgets.QWidget()
zsh: segmentation fault  python3

Some tests in python:

# Crashes after two times with SEGV
from PyQt5 import QtWidgets; app = QtWidgets.QApplication([]); QtWidgets.QWidget()
# Doesn't crash
from PyQt5 import QtWidgets; QtWidgets.QApplication([]); QtWidgets.QWidget()
# Crashes immediately with ABRT
from PyQt5 import QtWidgets; QtWidgets.QWidget()
# Doesn't crash
from PyQt5 import QtWidgets; app = QtWidgets.QApplication([])
# Doesn't crash
from PyQt5 import QtWidgets; app = QtWidgets.QApplication([]); QtWidgets.QWidget(); del app

My guess is the following: when QtWidgets.QApplication([]) is called, a new python wrapper is created, but it wraps a singleton. So when the second time app = QtWidgets.QApplication([]) is called:

  • python has an old app object that is losing its name, so it must be destroyed because:
  • A new python object is taking the app name

But the new python object is really a wrapper around the same C++ object. Therefore the second wrapper ends up empty.

Could you try https://github.com/spyder-ide/spyder-kernels/pull/189 to see if this fixes it?

Will take a look @impact27 thanks!

@impact27 I left a review at spyder-ide/spyder-kernels#189 . Thanks! :)

@dalthviz does it work for you with the fix?

Works like a charm on Mac @impact27 !

# Standard library imports
import sys

# Third party imports
from qtpy.QtWidgets import QApplication, QWidget


if __name__ == '__main__':
    app = QApplication([])
    window = QWidget()
    window.setGeometry(100, 100, 500, 300)
    window.setWindowTitle("PyQT Tuts!")
    window.show()
    window.raise_()
    sys.exit(app.exec_())
Was this page helpful?
0 / 5 - 0 ratings