0

A gui has a start button which launches a scraper in a thread so that the gui can be updated of its findings. How do i get my stop button to stop the scraping thread?

class Scrape:
    def __init__(self):
        #commence scraping the web

class Gui:

    def __init__(self):
        super(Gui, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        #events
        self.ui.start.clicked.connect(self.start_scraper)
        self.ui.stop.clicked.connect(self.stop_scraper)

    def start_scraper(self):
        self.browse = threading.Thread(target=Scrape)

    def stop_bot(self) -> None:
        raise SystemExit
Carlo Angelo
  • 393
  • 1
  • 6
  • 14
  • possible duplicate of [Is there any way to kill a Thread in Python?](http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python) – Nathan Tuggy Feb 22 '15 at 02:25
  • That thread doesnt deal with GUIs though... – Carlo Angelo Feb 22 '15 at 02:41
  • Sounds like you need to have your worker thread (scraper) listening on a message queue. So your gui thread can tell it to quit. This article may help http://eli.thegreenplace.net/2011/12/27/python-threads-communication-and-stopping. Sorry I don't have time to formulate an answer. – Paul Rooney Feb 22 '15 at 02:46
  • Paul, no problem. Any type of help whether its just pointing to a possible solution is much appreciated. Thanks – Carlo Angelo Feb 22 '15 at 02:49

1 Answers1

0

For myself, I prefer the following way, using a Queue as the channel for cross thread communication,it is thread safe and easy to use. It is all asynchronous communication.

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from Queue import Queue
from datetime import datetime


class MyThread(QThread):

    STOP_JOB_FLAG = None

    signal_thread_stop = pyqtSignal()

    def __init__(self, parent=None):
        super(MyThread, self).__init__(parent)
        self.mQueue = Queue()

    def startRun(self):
        if not self.isRunning():
            self.start()
            self.mQueue.put(datetime.now())
        else:
            self.mQueue.put(datetime.now())
            return

    def stopRun(self):
        if not self.isRunning():
            return
        else:
            self.mQueue.put(MyThread.STOP_JOB_FLAG)

    def run(self):
        while True:
            job = self.mQueue.get()
            if not job:
                qDebug("Thread run got None flag, will quit")
                self.signal_thread_stop.emit()
                break
            else:
                print "run " + str(job)
            self.mQueue.task_done()


class MyWidget(QWidget):
    def __init__(self, parent=None):
        super(MyWidget, self).__init__(parent)
        self.mLayout = QHBoxLayout(self)
        self.mStartBtn = QToolButton(self)
        self.mStopBtn = QToolButton(self)
        self.mStartBtn.setText("start")
        self.mStopBtn.setText("stop")
        self.setLayout(self.mLayout)
        self.mLayout.addWidget(self.mStartBtn)
        self.mLayout.addWidget(self.mStopBtn)
        self.mWorkerThread = MyThread()
        self.mStartBtn.released.connect(self.mWorkerThread.startRun)
        self.mStopBtn.released.connect(self.mWorkerThread.stopRun)
        self.mWorkerThread.signal_thread_stop.connect(self.handleRunFinished)

    def handleRunFinished(self):
        qDebug("handleRunFinished thread finished")

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = MyWidget()
    w.show()
    app.exec_()
Cui Heng
  • 1,265
  • 8
  • 10