PyQt app doesn't exit when i close the window - python

Whenever i execute the code and close the window, it closes,but the python console in the IDE doesn't return the exit code,when i try to run it again i get a warning dialog that says something like
No python console is selected to run main.py
So i have to close the IDE python console, and open a new one, then run the program in the new python console
I'm using spyder IDE 64 bits on windows
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
if __name__ == "__main__":
app = QApplication(sys.argv)
win = QMainWindow()
win.show()
sys.exit(app.exec_())

If you execute the code in a running (i)python console, you do not need to start a qapplication in the usual way, the two lines
win = QMainWindow()
win.show()
will be enough to get you running. This is because the console already has a (threaded) qapplication prepared for you.
The error message can be caused when no console has focus (i.e., perhaps the one you were using quit because of sys.exit(), or you clicked away etc). You need to simply click in an (i)python console to get it to be 'selected', and then the run button should work again.

Related

How can I create a PyQt5 UI that can be modified using a terminal that runs as a subprocess

I want to create a PyQt5 program that has the following:
A basic window:
app = QApplication([])
root = QMainWindow()
root.show()
app.exec_()
A terminal that runs a user input and can accept commands such as root.setWindowTitle("PyQt")
or if it were in a class className.setWindowTitle("PyQt").
This terminal must be the one from where you started running the program (xterm, terminus, gnome-terminal ...).
Final note, I have tried the QThread, multiprocess, threading, subprocess libraries to no avail.

How do I stop Spyder from clearing variables instead of executing my PyQt script?

When I execute my PyQt script in Spyder, it doesn't seem to do anything except clearing variables. When I execute it again, it works as expected.
As you can see below, I cannot reduce the code any further, but the problem remains unchanged.
Is this the expected behaviour? What am I doing wrong?
import sys
from PyQt5 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
window.show()
app.exec_()
In detail:
I open Spyder.
I execute the script. A window opens and I terminate by closing the window (expected behaviour).
I execute the script. After a few seconds, the console returns. Nothing seems to have happened except that the variables are gone (unexpected behaviour).
Repeat from 2...
The problem isn't so much that the variables are being cleared, but rather that the PyQt application cannot be run repeatedly within Spyder. It's a common issue that is addressed in the Spyder Wiki: How to run PyQt applications within Spyder.
It seems to be tied to the fact that Spyder is itself a Qt application. Specifically, the Wiki entry has this by way of an explanation:
The most common problem when running a PyQt application multiple times inside Spyder is that a QApplication instance remains in the namespace of the IPython console kernel after the first run. In other words, when you try to re-run your application, you already have a QApplication instance initialized.
The work-around is to make sure that the QApplication instance goes out of scope when your script exits, i.e., create it within the scope of a function. Using the simple example from above, it just comes down to this:
import sys
from PyQt5 import QtWidgets
def main():
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
window.show()
app.exec_()
main()

Unable to see app windows created by PySide2 in Spyder

I'm trying to run an app with PySide2 from Spyder 3.2.8 and Python 3.6.4 in Anaconda in a macOS 10.13.4.
attempt N°1
After having seen this stackoveflow page and this github page I changed my graphic backend from Inline to Automatic in Python > Preferences > IPython Console > Graphics and I tried to run the following script (script N°1):
script N°1
import sys
from PySide2.QtWidgets import *
# Create a Qt application
app = QApplication.instance()
if app is None:
print("print something")
app = QApplication(sys.argv)
# Create a Label and show it
label = QLabel("Hello World")
label.show()
# Enter Qt application main loop
app.exec_()
but got the following error message after running it:
Importing PySide2 disabled by IPython, which has
already imported an Incompatible QT Binding: pyqt5
There are similar reported issues here with matplotlib and here with ipython but it didn't help me (or I couldn't implement it properly). Then I tried to implement the content of this page about qtpy by changing the script N°1 in the following way:
script N°2
import os
os.environ['QT_API'] = 'pyside2'
from qtpy.QtWidgets import *
import sys
# Create a Qt application
app = QApplication.instance()
if app is None:
print("print something")
app = QApplication(sys.argv)
# Create a Label and show it
label = QLabel("Hello World")
label.show()
# Enter Qt application main loop
app.exec_()
attempt N°2
With Inline selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°2 , the app launches and I got print something printed in to the console. When closing the app, I got Out[1]: 0 in the console. However when I run the script again, no error message appears in the console but the window of the app doesn't show-up
attempt N°3
This time with Automatic selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°2 the first time, the app didn't launch and I got the following error message
/anaconda3/lib/python3.6/site-packages/qtpy/__init__.py:178: RuntimeWarning: Selected binding "pyside2" could not be found, using "pyqt5"
'using "{}"'.format(initial_api, API), RuntimeWarning)
Out[2]: -1
attempt N°4
With Automatic selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°1 after having changed the line from PySide2.QtWidgets import * to from PyQt5.QtWidgets import *: The app didn't launch and I got the following error message
Out[1]: -1
attempt N°5
With Inline selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°1 after having changed the line from PySide2.QtWidgets import * to from PyQt5.QtWidgets import *: The app launches and I got print something printed in to the console. I closed the app and got Out[1]: 0 in the console. However when I run the script again, no error message appears in the console but the window of the app doesn't show-up
N.B. this question is the continuation of that question
(Spyder maintainer here) Since the ipykernel package (which is used by Spyder to run code in its consoles) doesn't have event loop support for PySide2 as of May/2018 (as can be seen here), you won't be able to run PySide2 code inside Spyder, no matter what you try.
Notes:
The Automatic backend tries to select a suitable event loop for you, in this order: Qt5, Qt4, Tk and Inline. That's why it doesn't work in your case.
Every time you change a Graphics backend in Spyder, you need to restart the kernel of the console you want to run your code in. That's because you can only use one backend per console session (this is a limitation imposed by ipykernel, not by us). It's clear from your question that you're not doing that.
We're aware we fail to inform users when a kernel restart is necessary. We'll try to address that in our next major version (Spyder 4), to be released in 2019.
If you already know about qtpy, please use it to develop your apps instead of using PySide2 directly. That way you could work with PyQt5 for development in Spyder, but PySide2 for deployment, since qtpy takes care of working seamlessly with whatever binding is available.

pyqt5 application won't drop into a debugger - just crashes

I'm trying to write a pyqt5 application. It throws an exception from the Python side in a slot (i.e. callback) that responds to the user clicking a button. I run the application with
python -m pdb myapp.py
which begins with
# myapp.py
import sys
from PyQt5.QtCore import pyqtRemoveInputHook
pyqtRemoveInputHook()
from PyQt5.QtWidgets import QApplication, QWidget
from views import MainWindow
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
as per this question. I get the debugger prompt at program start and press c to continue. But when the crash happens, I get a stack trace and then a core dump. If I run with ipdb the core dump doesn't happen, but the program locks up before it can drop me into the debugger.
It seems like it's impossible to debug pyqt5 programs if the error is in a callback, although this worked fine in pyqt4 if I recall. How can I get a Python debugger working with pyqt5?

(PyQT4) Python instantly closes after launch

I am very new to PyQTt, I am working on Mac OS X, so i have installed PyQtX which works without any problems when importing PyQt4.
So i just tried making a very simple application:
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.show()
window.raise_()
When launching this with Python2, Python application shows in dock and instantly closes (Without showing any result).
Is it because i'm missing something on my system? What can a problem be?

Categories