[PyQt] C++ destructors and PyQt?
Bryan A. Jones
bjones at ece.msstate.edu
Mon Nov 3 22:07:47 GMT 2014
All,
Pardon the double post. I saw a few obvious bugs after hitting send. My
apologies. Here is the improved version.
Bryan
# Test program to ask about destructors and PyQt4.
import sys, time
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QThread, QTimer, QObject, pyqtSignal
class Worker(QObject):
def onStartWork(self):
time.sleep(1)
class ThreadController(QObject):
startWork = pyqtSignal()
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".
# Likewise, calling setParent after moving the object produces
# "QObject::setParent: Cannot set parent, new parent is in a different
# thread". 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 an ominous warning which will
# crash in a more complex program: "QThread: Destroyed while thread is
# still running".
#parent.aboutToQuit.connect(self.del_)
self.startWork.connect(self.worker.onStartWork)
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)
On Mon, Nov 3, 2014 at 3:59 PM, Bryan A. Jones <bjones at ece.msstate.edu>
wrote:
> 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)
>
--
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/088e4d85/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dest.py
Type: application/octet-stream
Size: 2727 bytes
Desc: not available
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20141103/088e4d85/attachment-0001.obj>
More information about the PyQt
mailing list