[PyQt] C++ destructors and PyQt?
Bryan A. Jones
bjones at ece.msstate.edu
Mon Nov 3 21:59:49 GMT 2014
All,
I’m confused when it comes to the proper way to mesh Qt’s model of creating
a tree of parented objects which destroy themselves when no longer used
with Python’s “delete it when I feel like it” garbage collector. In
particular, I’d like to shut down threads when the underlying Qt objects
are destroyed, but I can’t figure out how to do that. Any advice and wisdom
would be appreciated. I've attached same code with my thoughts.
Bryan
# Test program to ask about destructors and PyQt4.
import sys, time
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QThread, QTimer, QObject
class Worker(QObject):
def run(self):
time.sleep(1)
class ThreadController(QObject):
def __init__(self, parent):
QObject.__init__(self, parent)
# No parent object provided; if so, we get the error
# "QObject::moveToThread: Cannot move objects with a parent".
# Who will deallocate this object, since it has no parent? I
# assume the answer is "Python, maybe". Is that good enough?
self.worker = Worker()
self.workerThread = QThread(self)
self.worker.moveToThread(self.workerThread)
# Use method #2 below. Commnet out for a crash.
parent.aboutToQuit.connect(self.del_)
self.workerThread.start()
# I'd like to run when when ~ThreadController is invoked. That's quite
# differentfrom when __del__ is invoked. How?
#
# 1. Give up. Just invoke it manually. However, this is error-prone (i.e.
# I'll forget to do it at some point).
# 2. Connect app.aboutToQuit to this. This seems fairly reasonable, but
# it would feel cleaner to invoke when the destructor is invoked,
# rather than earlier. Also, this means that the QApplication would
# need to be passed to every thread, which might involve awkwardness
# in passing it through several intervening subclasses.
# 3. Connect destroyed(), which doesn't work -- this isn't emitted until
# the object is mostly dead, far after ~ThreadController was invoked,
# and won't be executed.
# 4. Have __del__ invoke this, which doesn't work -- it only happens after
# ~ThreadController has finihed.
def del_(self):
print('del_')
self.workerThread.quit()
self.workerThread.wait()
def __del__(self):
print('__del__')
# Crash when uncommented.
#self.del_()
if __name__ == '__main__':
app = QApplication(sys.argv)
# Exit the program shortly after the event loop starts up, but before the
# thread finishes.
QTimer.singleShot(200, app.exit)
# Start a thread
tm = ThreadController(app)
# Run the main event loop.
ret = app.exec_()
print('done')
sys.exit(ret)
--
Bryan A. Jones, Ph.D.
Associate Professor
Department of Electrical and Computer Engineering
231 Simrall / PO Box 9571
Mississippi State University
Mississippi state, MS 39762
http://www.ece.msstate.edu/~bjones
bjones AT ece DOT msstate DOT edu
voice 662-325-3149
fax 662-325-2298
Our Master, Jesus Christ, is on his way. He'll show up right on
time, his arrival guaranteed by the Blessed and Undisputed Ruler,
High King, High God.
- 1 Tim. 6:14b-15 (The Message)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20141103/d7fecd40/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dest.py
Type: application/octet-stream
Size: 2335 bytes
Desc: not available
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20141103/d7fecd40/attachment.obj>
More information about the PyQt
mailing list