2

I built a twitter crawler with GUI that fetches the latest 20 tweets from any given Twitter Account and saves them into a csv file.

The crawler should repeat crawling every x minutes (timeIntervall) for y times (times). The GUI freezes when the crawler is currently busy, so I tried to solve this with threading:

app = QtWidgets.QApplication(sys.argv)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Twitter Crawler")
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.onPushButtonClick)

    def onPushButtonClick(self):

        def working(self):
            url = self.ui.urlInput.text()
            timeIntervall = self.ui.timeIntervall.text()
            seconds = timeIntervall.split(":")
            seconds = int(seconds[0]) * 60 * 60 + int(seconds[1]) * 60
            times = self.ui.crawlcount.value()
            fetcher = ArticleFetcher(url)
            print(times)
            firstFetch = True

            for count in range(0, times):
                if firstFetch:
                    fetcher.fetch()
                    firstFetch = False
                else:
                    time.sleep(seconds)
                    fetcher.fetch()

        worker = threading.Thread(target=working, args=(self,))
        worker.start()
        worker.join()

window = MainWindow()
window.show()
sys.exit(app.exec())

After entering timeIntervall, times and pushButton is clicked, a worker thread is started which handles the crawling. The application is running, but GUI is still freezing.

I suspected that I would need another thread for the GUI and tried the following:

def gui():
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

rungui = threading.Thread(target=gui)
rungui.start()
rungui.join()

Now the GUI opens only very briefly and then closes again immediately.

Any suggestions how to solve this? Or is it maybe silly not to use the PyQt threading module?

Matthias
  • 4,481
  • 12
  • 45
  • 84
heslegend
  • 86
  • 8
  • 1
    Since you do `worker.join()` right in the GUI handling code and this call is blocking, the GUI will freeze. You could try creating another thread that would be responsible for spawning other threads on demand and waiting for them somehow (probably not using `join` at all). Then, in the GUI code, you send the function you need to run in a thread to this thread spawner and set a callback that'd be triggered when the task is complete. Or just use the tools already provided by the QT framework instead of rolling your own. – ForceBru Aug 11 '18 at 12:50

1 Answers1

0

The Thread's join() method waits for thread to complete. When you start your worker thread, let it run by itself. If you need to display it's progress, use Queue and send messages from worker thread to main thread (use get_nowait() in some timer loop to see if the worker thread has sent something important).

leotrubach
  • 1,509
  • 12
  • 15