title: Launch multiple threads from inside a pyqt thread
body: <p>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.</p>
  <pre><code>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()
  </code></pre>
  <p>However I am now moving this code to a GUI using Pyside.</p>
  <p>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.</p>
  <p>This is my core code</p>
  <pre><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(&quot;.zip&quot;):
                     fileList.append(filename)
                     count = count +1
  </code></pre>
  <p>If I try and add launching a thread from within the run function it causes an error stating that isn't allowed.</p>
  <p>How else could I achieve this?</p>
  <p>Thanks</p>
  <p>EDIT##</p>
  <p>Full example</p>
  <pre><code>#!/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(&quot;Run&quot;)
      runButton.clicked.connect(self.unzip)
      exitButton = QtGui.QPushButton(&quot;Exit&quot;)
      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(&quot;Find Zip File&quot;))
  
      searchBox = QtGui.QHBoxLayout()
      self.fileLabel = QtGui.QLabel(self.tr(&quot;Location: &quot;))
      self.fileLineEdit = QtGui.QLineEdit()
      self.fileDialogBtn =  QtGui.QPushButton(&quot;Browse&quot;)
      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, &quot;Open Directory&quot;, 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',
          &quot;Are you sure to quit?&quot;, 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 &quot;finished&quot;
  
  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(&quot;.shp&quot;):
                  fileList.append(filename)
                  count += 1
      print count
  
      list1 = []
      list2 = []
  
      for shpfile in fileList:
          if &quot;line&quot; in shpfile:
              list1.append(shpfile)
          elif &quot;point&quot; 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 &quot;got here&quot;
  
  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 &quot;thread 1 count %s&quot; %(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 &quot;thread 2 count %s&quot; %(count)
  
      return
  
  def main():
  
  app = QtGui.QApplication(sys.argv)
  ex = Example()
  sys.exit(app.exec_())
  
  
  if __name__ == '__main__':
      main()
  </code></pre>
  <p>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.</p>
  <p>So the results I get look like this</p>
  <p>5635
  finishedthread 1 count 2858</p>
  <p>thread 2 count 2777here</p>
  <p>here</p>
  <p>So you can see the comment &quot;finished&quot; appears before the other code &quot;thread count 1&quot; etc, which proves that it thinks it has finished.</p>
  <p>Anyway I can get them to communicate?</p>
  <p>thanks</p>
  <h2>EDIT 2</h2>
  <p>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??</p>
  <pre><code>#!/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(&quot;Run&quot;)
          runButton.clicked.connect(self.unzip)
          exitButton = QtGui.QPushButton(&quot;Exit&quot;)
          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(&quot;Find Zip File&quot;))
  
          searchBox = QtGui.QHBoxLayout()
          self.fileLabel = QtGui.QLabel(self.tr(&quot;Location: &quot;))
          self.fileLineEdit = QtGui.QLineEdit()
          self.fileDialogBtn =  QtGui.QPushButton(&quot;Browse&quot;)
          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, &quot;Open Directory&quot;, 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',
              &quot;Are you sure to quit?&quot;, 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 &quot;unzip thread finished&quot;
  
  class Worker(QtCore.QObject):
      finished = pyqtSignal()
  
      def __init__(self, filepath):
          QtCore.QObject.__init__(self)
  
          self.filePath = filepath
  
      def run(self):
          self.threadcount = 0
          print &quot;finding files&quot;
          fileList = []
          count = 0
          for dirname, dirnames, filenames in os.walk(self.filePath):
              for filename in filenames:
                  if filename.endswith(&quot;.shp&quot;):
                      fileList.append(filename)
                      count += 1
          print count
  
          self.list1 = []
          self.list2 = []
  
          for shpfile in fileList:
              if &quot;line&quot; in shpfile:
                  self.list1.append(shpfile)
              elif &quot;point&quot; 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 &quot;extra threads finished&quot;
                  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 &quot;thread 1 count %s&quot; %(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 &quot;thread 2 count %s&quot; %(count)
  
          self.finished.emit()
  
  def main():
  
      app = QtGui.QApplication(sys.argv)
      ex = Example()
      sys.exit(app.exec_())
  
  
  if __name__ == '__main__':
      main()
  </code></pre>