title: How to run a "While Loop" with PyQt5?
body: <p>I made one script some time ago to record the monitor frames of the user and now I am trying to create a GUI for it. For now it has only a START and a STOP button, but the STOP button does not stop the recording.</p>
  
  <p>How could I change my <code>stop_thread</code> function for it to work? Should I terminate the worker first and then the thread? How can I terminate the worker anyway?</p>
  
  <pre><code>import sys
  from PyQt5.QtWidgets import (QWidget,
                               QPushButton, QApplication, QGridLayout)
  from PyQt5.QtCore import QThread, QObject
  
  
  class Worker(QObject):
  
      def __init__(self, parent=None):
          QObject.__init__(self, parent=parent)
  
      def do_work(self):
          i = 1
          while True:
              print(i)
              QThread.sleep(1)
              i = i + 1
  
      def stop(self):
          print("stopped")
          self.deleteLater() # How do I stop it?
  
  
  class Gui(QWidget):
  
      def __init__(self):
          super().__init__()
          self.initUI()
  
      def initUI(self):
  
          # Buttons:
          self.btn_start = QPushButton('Start')
          self.btn_start.resize(self.btn_start.sizeHint())
          self.btn_start.move(50, 50)
          self.btn_stop = QPushButton('Stop')
          self.btn_stop.resize(self.btn_stop.sizeHint())
          self.btn_stop.move(150, 50)
  
          # GUI title, size, etc...
          self.setGeometry(300, 300, 300, 220)
          self.setWindowTitle('ThreadTest')
          self.layout = QGridLayout()
          self.layout.addWidget(self.btn_start, 0, 0)
          self.layout.addWidget(self.btn_stop, 0, 50)
          self.setLayout(self.layout)
  
          # Thread:
          self.thread = QThread()
          self.worker = Worker()
          self.worker.moveToThread(self.thread)
  
          self.thread.started.connect(self.worker.do_work) # when thread starts, start worker
          self.thread.finished.connect(self.worker.stop) # when thread finishes, stop worker
  
          # Start Button action:
          self.btn_start.clicked.connect(self.thread.start)
  
          # Stop Button action:
          self.btn_stop.clicked.connect(self.stop_thread)
  
          self.show()
  
      # When stop_btn is clicked this runs. Terminates the worker and the thread.
      def stop_thread(self):
          print("It should stop printing numbers now and not crash")
          self.worker.disconnect()
          self.thread.terminate()
  
  
  if __name__ == '__main__':
      app = QApplication(sys.argv)
      gui = Gui()
      sys.exit(app.exec_())
  </code></pre>
  
  <p><strong>EDIT:</strong> While <a href="https://stackoverflow.com/a/49887670/2648551">MalloyDelacroix answer</a> worked for some time, I've now run into a problem:</p>
  
  <p>If <code>do_work</code> from <code>Worker</code> is an imported function which loops forever, how can I stop it with a button click? I want to force close it.</p>
  
  <pre><code>from test import s_main
  
  class Worker(QObject):
  
      finished = pyqtSignal()  # give worker class a finished signal
  
      def __init__(self, parent=None):
          QObject.__init__(self, parent=parent)
          self.continue_run = True  # provide a bool run condition for the class
  
      def do_work(self):
  
          s_main()
  
          self.finished.emit()  # emit the finished signal when the loop is done
  
      def stop(self):
          self.continue_run = False  # set the run condition to false on stop
  </code></pre>
  
  <p><em>test.py:</em></p>
  
  <pre><code>def s_main():
      i = 1
      while True:
          i = i + 1
          print(i)
  </code></pre>