PDA

View Full Version : QThread to run one or more QProcess



smhall316
27th September 2011, 20:39
I am having some problems with running one or more QProcess's in a single QThread. My goal is to run one process at a time in a single thread, one after another. I am able to successfully do that but as these process's run I am noticing that my memory for the python GUI just starts consuming all of the memory over time. I made basic little command line programs which simply iterate to a value to simulate a long running program.

When I start a process I wait for it to end using waitForFinished(-1). I assume since this is being done in a thread it should not affect my core Python GUI. Am I not using the QProcess within a QThread correctly? If I take out the waitForFinished(-1) then I always get an error that the thread was destroyed before it had completed. I am attaching the Python code below

Thanks In Advanced!!


#!/usr/bin/env python
'''
Try making a responsive gui with programs running in the background
'''

# Python modules
import sys

# PyQt4 Modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class ThreadTest(QDialog):

def __init__(self, parent=None):
super(ThreadTest, self).__init__(parent)

self.setMinimumWidth(400)
self.setMinimumHeight(400)
self.setWindowTitle("Thread Test")

self.thread = IndividualThread()

self.pbar = QProgressBar()
self.label = QLabel("")
self.p1Btn = QPushButton("Run Program 1")
self.p2Btn = QPushButton("Run Program 2")
self.p3Btn = QPushButton("Run Program 3")

self.pbar.setOrientation(Qt.Horizontal)
self.pbar.setRange(0,100)
self.pbar.setValue(0)
self.pbar.setInvertedAppearance(False)
self.pbar.setTextVisible(False)

box = QVBoxLayout()
box.addWidget(self.p1Btn)
box.addWidget(self.p2Btn)
box.addWidget(self.p3Btn)
box.addWidget(self.label, 0, Qt.AlignCenter)
box.addWidget(self.pbar)

self.setLayout(box)

self.timer = QTimer()

self.connect(self.p1Btn , SIGNAL('pressed()'), self.runP1)
self.connect(self.p2Btn , SIGNAL('pressed()'), self.runP2)
self.connect(self.p3Btn , SIGNAL('pressed()'), self.runP3)

self.connect(self.timer , SIGNAL('timeout()') , self.onTimeout)
self.connect(self.thread , SIGNAL('started()') , self.onThreadStarted)
self.connect(self.thread , SIGNAL('finished()'), self.onThreadFinished)

self.connect(self.dsn_thread, SIGNAL('threadInfo'), self.onThreadInfo)

def enableButtons(self, enable):
self.p1Btn.setEnabled(enable)
self.p2Btn.setEnabled(enable)
self.p3Btn.setEnabled(enable)
self.dsnBtn.setEnabled(enable)

def runP1(self):

self.label.setText("Running program 1")
self.thread.setCommand("/home/hall000s/python/threads/prog1_lnx")
self.thread.start()

def runP2(self):
self.label.setText("Running program 2")
self.thread.setCommand("/home/hall000s/python/threads/prog2_lnx")
self.thread.start()

def runP3(self):
self.label.setText("Running program 3")
self.thread.setCommand("/home/hall000s/python/threads/prog3_lnx")
self.thread.start()

def onThreadInfo(self, msg):
self.label.setText(msg)

def onTimeout(self):
# Update the progress bar
value = self.pbar.value()

# Going forward or backwards?
if self.pbar.invertedAppearance():
if value-2 < self.pbar.minimum():
self.pbar.setValue(self.pbar.minimum())
self.pbar.setInvertedAppearance(False)
else:
self.pbar.setValue(value-2)
else:
if value+2 > self.pbar.maximum():
self.pbar.setValue(self.pbar.maximum())
self.pbar.setInvertedAppearance(True)
else:
self.pbar.setValue(value+2)

def onThreadStarted(self):
print "Thread has been started"
self.timer.start(10)
self.enableButtons(False)

def onThreadFinished(self):
print "Thread has finished"
self.timer.stop()
self.enableButtons(True)
self.pbar.setValue(0)
self.label.setText("")

class IndividualThread(QThread):

def __init__(self, parent=None):
super(IndividualThread, self).__init__(parent)

self.args = ""
self.command = ""

def setArguments(self, arguments):
self.args = arguments

def setCommand(self, command):
self.command = command

def run(self):
process = QProcess()
process.start(self.command, self.args)
process.waitForFinished(-1)

#
# MAIN
#
if __name__ == '__main__':

# Order matters from here on.
app = QApplication(sys.argv)
form = ThreadTest()
form.show()
sys.exit(app.exec_())


Added after 1 33 minutes:

Ignore this, I figured out the problem. I wasn't paying attention to the amount of data I was writing out to stderr and stdout in my silly program, which was causing the memory to increase as the program executed.