I am writting a desktop application with PyQt4 and all of the sudden it started to crash on exit.
I reviewed all of my code to make sure I wasn't doing anything funny to make it crash and I don't think there's anything wrong with the code.
I have seen some complaints about this before but it was related to a previous version and people advised to upgrade PyQt4 to the latest version and so I did, but that didn't help with the crashing problem.
So I ask, is there anything that can lead to this behavior with PyQt4, do I need to do some kind on termination procedure to cleanup Qt or anything else I am missing?
I had the same problem with a simple hello world application (QDialog with 20 labels). Weirdly the problem disappears with 10 labels.
I solved by forcing exit as follows:
def closeEvent(self, event):
exit()
This happens on Windows with PyQt v4.10.3 for Python v2.7 (x32) on VirtualBox.
A debugger will only tell us what we already know: The application crashes on exit.
You probably need to set an active window which, when closed, will result in deterministic garbage collection and a clean application exit. There are more proper ways to do this, but the simpl;e example below should require minimum code changes, and is based on a dialog application that I wrote and works fine.
#The application
app = QtGui.QApplication(sys.argv)
#The main window
MainWindow = QtGui.QMainWindow()
app.setActiveWindow(MainWindow) #<---- This is what's probably missing
#the ui
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
#start the application's exec loop, return the exit code to the OS
exit(app.exec_())
Related
I'm developing PyQt5 application of medium complexity. It has various widgets (both native and third-party) and Qthreads. It woks fine most of the time, but once in about 5 times the application hangs in the background after I exit it.
Here is how I define closeEvent:
def closeEvent(self, event):
qApp.quit()
And I also have defined a quit_action and connected it to the qApp.quit() like this:
self.quit_action.triggered.connect(qApp.quit)
I launch the PyQt5 application the standard way:
app = QApplication([])
window = GUIWindow()
window.show()
sys.exit(app.exec())
I have no idea how to debug such strange error. It happens only once in a few times and I can't reproduce the error.
I run the application in the console:
python main.py
and usually I can close the application without a problem. But once in a few times after I close the application (either by clicking on "x" button of the window or by triggering the quit_action in the menu) the window disappears and the process hangs in the background. I have to press "Ctlr+Z" and then kill the process.
What is the strategy to debug such strange error? How can find what exactly causes the freezing of the application?
This kind of bugs are hard to isolate. It looks like my particular bug emerges as a result of combination of several widgets of the app and it's hard to even provide a minimal working example that reproduces the error. Not to mention the error only happens once in a few runs.
It looks like I've found the main culprit for the bug by inspecting the hanging process through the gdb (see the question from stackoverflow Is there a way to attach a debugger to a multi-threaded Python process?).
When my application has frozen again - I attached to the process via the gdb, investigated threads and found the problematic thread.
EDIT: A temporary solution to make PyQt application close even when qApp.quit() doesn't help:
def closeEvent(self, event):
qApp.quit()
sys.exit()
I am working for the first time towards the implementation of a very simple GUI in PyQt5, which embeds a matplotlib plot and few buttons for interaction.
I do not really know how to work with classes so I'm making a lot of mistakes, i.e. even if the functionality is simple, I have to iterate a lot between small corrections and verification.
For some reason I would like to debug, however, the whole process is made much, much slower by the fact that at any other try, the python kernel dies and it needs restarting (all done automatically) several times.
That is, every time I try something that should last maybe 5 secs, I end up spending a minute.
Anybody know where to look to spot what is causing these constant death/rebirth circles?
I have been using spyder for some time now and I never experienced this behaviour before, so I'm drawn to think it might have to do with PyQt, but that's about how far I can go.
This issue is tracked here
You can learn all the details there, but in a nutshell when running from inside spyder - which itself is a QApplication, the main loop should read:
if __name__ == '__main__':
import sys
from PyQt5 import QtWidgets
fig1 = Figure()
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
main = Main()
main.addmpl(fig1)
main.show()
sys.exit(app.exec_())
The if/then check on the existence of a QApplication avoids a segmentation fault which happens if one tries to launch multiple instances at one time, as explained here
I had a similar problem and found that my application only worked when the graphics settings inside Spyder are set to inline. This can be done at Tools -> Preferences -> IPython console -> Graphics, now change the Backends to inline.
Hope this helps.
Ok here is my problem:
I want to create a PyQt4 Gui, which can be executed from a python console (tested with IDLE, Spyder Console and IPython Console) and then allows the user to change and view variables. After closing the app the user should be able to do further work with the variables in the console. But by closing the Gui the Kernel crashes and it is not possible to make any new input to the console.
I'm working with Python 2.7 and PyQt4. I am using the following code to start an close the application:
app=QtGui.QApplication(sys.argv)
MainApp=plottest()
MainApp.show()
sys.exit(app.exec_())
The easy solution here https://www.reddit.com/r/learnpython/comments/45h05k/solved_kernel_crashing_when_closing_gui_spyder/
only put
if __name__ == "__main__":
app=0 #This is the solution
app = QtGui.QApplication(sys.argv)
MainApp = Dice_Roller()
MainApp.show()
sys.exit(app.exec_())
What you need to do is:
Check that there isn't already a QApplication instance when trying to create a new one
Ensure that the QApplication object is deleted after it's been closed
(See simple IPython example raises exception on sys.exit())
# Check if there's a pre-existing QApplication instance
# If there is, use it. If there isn't, create a new one.
app = QtGui.QApplication.instance()
if not app:
app = QtGui.QApplication(sys.argv)
# Ensure that the app is deleted when we close it
app.aboutToQuit.connect(app.deleteLater)
# Execute the application
MainApp = plottest()
MainApp.show()
sys.exit(app.exec_())
Using this code you can rerun the application as many times as you want in IPython, or anywhere else. Every time you close your Qt application, the app object will be deleted in python.
I do not think you mean a kernel crash. Rather, I think you are talking about exiting the python console. This is caused by sys.exit(app.exec_()). For example try (for example in spyder) the following two codes:
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
widget = QtGui.QWidget()
widget.setWindowTitle('simple')
widget.show()
#sys.exit(app.exec_())
Here you should get an empty window and the python console will stay alive. The second one, where sys.exit(app.exec_()) is included, will exit the python console at the end and the window disappears:
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
widget = QtGui.QWidget()
widget.setWindowTitle('simple')
widget.show()
sys.exit(app.exec_())
I hope this helps.
I still don't know the issue and solution. None of the above worked for me. Currently I am coding in the spyder GUI and running on "cmd" by giving 'python' command. In CMD, it is working fine.
Update the solution if I get it. :-)
I think that your problem is that python console closes (its not kernel crash). For example in Spyder python icon on top of console window becomes grey and you cant do anything besides running another console.
Anyway, you should write app.exec() instead of sys.exit(app.exec()).
I believe sys.exit(app.exec()) passes exit code to console and closes it. Using simple app.exec() won't close console.
Concluding your code should look like:
app=QtGui.QApplication(sys.argv)
MainApp=plottest()
MainApp.show()
app.exec_()
I hope it helps.
hdunn's answer worked for me. Have deleted sys.exit() to avoid exiting the application totally. Performing the first step alone, as suggested by others in github forum, solved part of the problem but window never showed up, nor any error message. Performing the second part solved everything like a charm! Thans, hdunn!
# Check if there's a pre-existing QApplication instance
# If there is, use it. If there isn't, create a new one.
app = QtGui.QApplication.instance()
if not app:
app = QtGui.QApplication(sys.argv)
# Ensure that the app is deleted when we close it
app.aboutToQuit.connect(app.deleteLater)
# Execute the application
MainApp = plottest()
MainApp.show()
app.exec_()
i just noticed that when i run a pyqt application and close it, the application closes , but the process is still alive. Apparently the process that was running does not close even after closing the application.
Traceback (most recent call last):
File "F:\Projects\XYZ\XYZ\XYZ.py", line 414, in <module>
sys.exit(app.exec_())
SystemExit: 0
When i searched online , its says that if the return value is 0 , it is a normal termination. As you see the process keep on pilling up as i run the application.
So how do i overcome this problem?
SOLUTION
This a quick fix , that i was able to make to solve this problem.
import psutil, os
def kill_proc_tree(pid, including_parent=True):
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
child.kill()
if including_parent:
parent.kill()
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow() # <-- Instantiate QMainWindow object.
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
app.exec_()
me = os.getpid()
kill_proc_tree(me)
This looks like a problem specific to IDLE.
There are several issues on the python bug tracker that are closely related (e.g. 8093 and 12540), but they are now closed and resolved as "fixed".
Since it appears that you are using a very old version of python (2.5), you should be able to solve the problem by upgrading.
Have you tried the following?
sys.exit(app.exec_)
It's common practice among PyQt developers, and an easy way to cleanly quit your program. You should, however, upgrade to Python 2.7 or Python 3.3.
If I'm trying to create a window or prompt a file dialog in the IDLE shell, nothing opens and the shell restarts. Is this a bug of some kind? I can't find anything about it. I'm new to PyQt (and Python in general) but had been able to get tutorials to work correctly. The last day or so, if I open IDLE and import PyQt4, QtGui, etc and then run something simple like QFileDialog.getOpenFileName, the shell just restarts. Any ideas?
You need to have a QApplication before you can use anything else from PyQt. Try rereading some of the tutorials you followed, or do a few more. This one for example.
In the first code sample of the above tutorial, pay special attention to these lines (I've included the comments from the tutorial for convenience):
app = QtGui.QApplication(sys.argv)
Every PyQt4 application must create an application object. The
application object is located in the QtGui module. The sys.argv
parameter is a list of arguments from the command line. Python scripts
can be run from the shell. It is a way, how we can control the startup
of our scripts.
and
sys.exit(app.exec_())
Finally, we enter the mainloop of the application. The event handling
starts from this point. The mainloop receives events from the window
system and dispatches them to the application widgets. The mainloop
ends, if we call the exit() method or the main widget is destroyed.
The sys.exit() method ensures a clean exit. The environment will be
informed, how the application ended.
The exec_() method has an underscore. It is because the exec is a
Python keyword. And thus, exec_() was used instead.
It appears you might have forgotten about these. Or maybe you haven't realized that this means that you normally can't use PyQt with a running event loop in the interactive shell. However, there is a trick for that, see here.