I currently have a script the reads a folder of files (thousands of files) into a list which is then split into 4 sub lists. I then have a thread running for each list. This is very easy to achieve in a python script.
thread1fileList, thread2fileList, thread3fileList, thread4fileList = load.sortFiles(fileList)
threads = [threading.Thread(target=load.threadLoad, args=(fileList, ))
for fileList in (thread1fileList, thread2fileList, thread3fileList, thread4fileList)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
However I am now moving this code to a GUI using Pyside.
I have been able to create a thread that reads the folder of files (to make sure the GUI is still responsive) but I cannot launch 4 new threads from inside the Qt.Thread to work on the file list.
This is my core code
self.unzipThread = UnzipThread()
self.unzipThread.start()
self.unzipThread.finished.connect(self.finishUp()) #finsihUp provides the final page of the wizard
class UnzipThread(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
for dirname, dirnames, filenames in os.walk(directorypath):
for filename in filenames:
if filename.endswith(".zip"):
fileList.append(filename)
count = count +1
If I try and add launching a thread from within the run function it causes an error stating that isn't allowed.
How else could I achieve this?
Thanks
EDIT##
Full example
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PySide import QtGui, QtCore
import os
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
runButton = QtGui.QPushButton("Run")
runButton.clicked.connect(self.unzip)
exitButton = QtGui.QPushButton("Exit")
exitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
hbox = QtGui.QHBoxLayout()
hbox.addWidget(runButton)
hbox.addStretch(1)
hbox.addWidget(exitButton)
titleBox = QtGui.QVBoxLayout()
titleLabel = QtGui.QLabel(self.tr("Find Zip File"))
searchBox = QtGui.QHBoxLayout()
self.fileLabel = QtGui.QLabel(self.tr("Location: "))
self.fileLineEdit = QtGui.QLineEdit()
self.fileDialogBtn = QtGui.QPushButton("Browse")
self.fileDialogBtn.clicked.connect(self.openDirectoryDialog)
searchBox.addWidget(self.fileLabel)
searchBox.addWidget(self.fileLineEdit)
searchBox.addWidget(self.fileDialogBtn)
titleBox.addWidget(titleLabel)
titleBox.addStretch(1)
titleBox.addLayout(searchBox)
titleBox.addStretch(1)
titleBox.addLayout(hbox)
self.setLayout(titleBox)
self.resize(500, 300)
self.center()
self.setWindowTitle('Example')
self.show()
def unzip(self):
self.unzipThread = UnzipThread(self.filePath)
self.unzipThread.start()
self.unzipThread.finished.connect(self.finishUp)
def openDirectoryDialog(self):
flags = QtGui.QFileDialog.DontResolveSymlinks | QtGui.QFileDialog.ShowDirsOnly
directory = QtGui.QFileDialog.getExistingDirectory(self, "Open Directory", os.getcwd(),flags)
self.fileLineEdit.setText(directory)
self.filePath = self.fileLineEdit.text()
def center(self):
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def finishUp(self):#yet to code up to GUI log windows
print "finished"
class UnzipThread(QtCore.QThread):
def __init__(self, filepath):
QtCore.QThread.__init__(self)
self.filePath = filepath
def run(self):
fileList = []
count = 0
for dirname, dirnames, filenames in os.walk(self.filePath):
for filename in filenames:
if filename.endswith(".shp"):
fileList.append(filename)
count += 1
print count
list1 = []
list2 = []
for shpfile in fileList:
if "line" in shpfile:
list1.append(shpfile)
elif "point" in shpfile:
list2.append(shpfile)
else:
pass
self.processThread1 = ProcessThread1(list1)
self.processThread1.start()
self.processThread1.finished.connect(self.threadCount)
self.processThread2 = ProcessThread2(list2)
self.processThread2.start()
self.processThread2.finished.connect(self.threadCount)
return
def threadCount(self):
print "got here"
class ProcessThread1(QtCore.QThread):
def __init__(self, filelist):
QtCore.QThread.__init__(self)
self.filelist = filelist
def run(self):
count = 0
for textfile in self.filelist:
count +=1
print "thread 1 count %s" %(count)
return
class ProcessThread2(QtCore.QThread):
def __init__(self, filelist):
QtCore.QThread.__init__(self)
self.filelist = filelist
def run(self):
count = 0
for textfile in self.filelist:
count +=1
print "thread 2 count %s" %(count)
return
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
In stripping out alot of my code to provide this example it seems running a thread from inside my QT.Thread works however the initial thread believes it has finished before the threads that are running have finished.
So the results I get look like this
5635
finishedthread 1 count 2858
thread 2 count 2777here
here
So you can see the comment "finished" appears before the other code "thread count 1" etc, which proves that it thinks it has finished.
Anyway I can get them to communicate?
thanks
EDIT 2
So I have now changed my code to use QObjects and movetoThread but how do I properly determine that both sub threads have finished. This is now my code. I have had to to use a thread counter and a While loop to determine if both sub threads have finished. There must be a better way??
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PySide import QtGui, QtCore
import os
from PySide.QtCore import Signal as pyqtSignal
import time
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
runButton = QtGui.QPushButton("Run")
runButton.clicked.connect(self.unzip)
exitButton = QtGui.QPushButton("Exit")
exitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
hbox = QtGui.QHBoxLayout()
hbox.addWidget(runButton)
hbox.addStretch(1)
hbox.addWidget(exitButton)
titleBox = QtGui.QVBoxLayout()
titleLabel = QtGui.QLabel(self.tr("Find Zip File"))
searchBox = QtGui.QHBoxLayout()
self.fileLabel = QtGui.QLabel(self.tr("Location: "))
self.fileLineEdit = QtGui.QLineEdit()
self.fileDialogBtn = QtGui.QPushButton("Browse")
self.fileDialogBtn.clicked.connect(self.openDirectoryDialog)
searchBox.addWidget(self.fileLabel)
searchBox.addWidget(self.fileLineEdit)
searchBox.addWidget(self.fileDialogBtn)
titleBox.addWidget(titleLabel)
titleBox.addStretch(1)
titleBox.addLayout(searchBox)
titleBox.addStretch(1)
titleBox.addLayout(hbox)
self.setLayout(titleBox)
self.resize(500, 300)
self.center()
self.setWindowTitle('Example')
self.show()
def unzip(self):
thread = self.thread = QtCore.QThread()
worker = self.worker = Worker(self.filePath)
worker.moveToThread(thread)
worker.finished.connect(worker.deleteLater)
worker.finished.connect(thread.quit)
thread.started.connect(worker.run)
thread.finished.connect(self.finishUp)
thread.start()
def openDirectoryDialog(self):
flags = QtGui.QFileDialog.DontResolveSymlinks | QtGui.QFileDialog.ShowDirsOnly
directory = QtGui.QFileDialog.getExistingDirectory(self, "Open Directory", os.getcwd(),flags)
self.fileLineEdit.setText(directory)
self.filePath = self.fileLineEdit.text()
def center(self):
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def finishUp(self):#yet to code up to GUI log windows
print "unzip thread finished"
class Worker(QtCore.QObject):
finished = pyqtSignal()
def __init__(self, filepath):
QtCore.QObject.__init__(self)
self.filePath = filepath
def run(self):
self.threadcount = 0
print "finding files"
fileList = []
count = 0
for dirname, dirnames, filenames in os.walk(self.filePath):
for filename in filenames:
if filename.endswith(".shp"):
fileList.append(filename)
count += 1
print count
self.list1 = []
self.list2 = []
for shpfile in fileList:
if "line" in shpfile:
self.list1.append(shpfile)
elif "point" in shpfile:
self.list2.append(shpfile)
else:
pass
thread1 = self.thread1 = QtCore.QThread()
worker1 = self.worker1 = Process1(self.list1)
worker1.moveToThread(thread1)
worker1.finished.connect(worker1.deleteLater)
worker1.finished.connect(thread1.quit)
thread1.started.connect(worker1.run)
thread1.finished.connect(self.finishUp)
thread1.start()
thread2 = self.thread2 = QtCore.QThread()
worker2 = self.worker2 = Process2(self.list2)
worker2.moveToThread(thread2)
worker2.finished.connect(worker2.deleteLater)
worker2.finished.connect(thread2.quit)
thread2.started.connect(worker2.run)
thread2.finished.connect(self.finishUp)
thread2.start()
def finishUp(self):
self.threadcount += 1
while True:
if self.threadcount != 2:
break
else:
print "extra threads finished"
self.finished.emit()
break
class Process1(QtCore.QObject):
finished = pyqtSignal()
def __init__(self, filelist):
QtCore.QObject.__init__(self)
self.filelist = filelist
def run(self):
count = 0
for textfile in self.filelist:
count +=1
print "thread 1 count %s" %(count)
self.finished.emit()
class Process2(QtCore.QObject):
finished = pyqtSignal()
def __init__(self, filelist):
QtCore.QObject.__init__(self)
self.filelist = filelist
def run(self):
count = 0
for textfile in self.filelist:
count +=1
time.sleep(15)
print "thread 2 count %s" %(count)
self.finished.emit()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()