I have a problem with stack frames hanging around after exceptions in PyQt
objects.
A particular method on a PyQt object is connected to a signal. This method
is called because of the signal is raised.
If I get an uncaught exception in that method, then there appears to be a
stack frame left around which doesn't get cleaned up. This means that the
python part of the PyQt object isn't deleted until the end of the program
(the C++ is, leading to the nasty exception about the C++ object not
existing).
This wouldn't be so bad because you shouldn't leave uncaught exceptions,
however if you use an exception hook then the same thing happens. You end up
with PyQt objects which never get deleted until the end of the program.
There's an example program here. Click on the button to create a new dialog.
If you close the dialog, __del__ gets called and prints a message. If you
click on the exception button in the dialog first, __del__ never gets
called.
You can insert gc.get_referrers to see the reference to the dialog appears
to be in a frame object.
I assume this is a PyQt bug as I can't replicate it with pure Python, but
it's not simple to reproduce.
Jeremy
--
http://www.jeremysanders.net/
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class DataCreateDialog(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
self.setAttribute(Qt.WA_DeleteOnClose)
layout = QVBoxLayout()
exceptionbutton = QPushButton("raise exception!", self)
self.connect( exceptionbutton, SIGNAL('clicked()'),
self.exceptionButtonClicked )
layout.addWidget(exceptionbutton)
self.setLayout(layout)
def exceptionButtonClicked(self):
"""Cause exception if button pressed"""
print "here"
xxx
def __del__(self):
print "deleted dialog okay", self
def hideEvent(self, event):
"""Emits dialogFinished if hidden."""
if not event.spontaneous():
print "dialog got hide event", self
self.emit( SIGNAL('dialogFinished'), self )
return QDialog.hideEvent(self, event)
class Window(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
createbutton = QPushButton("make test dialog")
self.connect( createbutton, SIGNAL('clicked()'),
self.createButtonClicked )
layout.addWidget(createbutton)
self.setLayout(layout)
def createButtonClicked(self):
"""Create button pressed."""
# make new dialog and keep reference
self.d = DataCreateDialog(self)
self.connect(self.d, SIGNAL('dialogFinished'), self.dialogFinished)
self.d.show()
def dialogFinished(self):
"""Delete reference."""
del self.d
def excepthook(excepttype, exceptvalue, tracebackobj):
return
#sys.excepthook = excepthook
app = QApplication([])
w = Window()
w.show()
app.exec_()
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt