Search code examples
pythonpyqt4qthreadftputil

Pyqt use QThread but GUI still not responding


I tried to download file from FTP to network shared folder(file size might 500mb or bigger) but every time when clicked "Start" the GUI will show "not responding" even using QThread

Did I do it wrong anything?

main.py

# -*- coding: utf-8 -*-
from PyQt4 import QtGui
import ftp100



class main_windows(QtGui.QWidget):
    def __init__(self):
        super(main_windows, self).__init__()
        self._count = 0
        self.Ftpallobject = []

    def init(self):

        #PASS SOME GUI CODE

        button_go = QtGui.QPushButton('GO')
        button_go.clicked.connect(self.Ftpstart)

        self.fp = ftp100.ftpmethod()
        self.fp.requestSignal_getinfo.connect(self.Ftpallobject)



    def SendFtpInfo(self):
        self.fp.update_getinfo.emit(self.allobject)

    def Ftpstart(self):
        self.fp.run()

ftp.py

# -*- coding: utf-8 -*-
from PyQt4 import QtCore
import ftputil

class ftpmethod(QtCore.QThread):
    requestSignal_getinfo = QtCore.pyqtSignal()
    update_getinfo = QtCore.pyqtSignal(list)

    def __init__(self, parent=None):
        super(ftpmethod, self).__init__(parent)
        self._count = 0
        self.ftpinfo = []
        self.update_getinfo.connect(self.getinfo)

    def run(self):
        self.requestSignal_getinfo.emit()
        while self._count<1:
            for i in self.ftpinfo:
                site = "".join(str(i[2].text()))
                account = "".join(str(i[0].text()))
                pwd = "".join(str(i[1].text()))
                filepath = "".join(str(i[3].text()))
                filename = "".join(str(i[4].text()))
                downloadtolocal = "".join(str(i[7].text()))+"".join(str(i[4].text()))
                print site,account,pwd,filepath,filename,downloadtolocal
                try:
                    with ftputil.FTPHost(site,account,pwd) as host:
                        if filepath=='':
                            host.download(filename,downloadtolocal)
                        else:
                            host.chdir(filepath)
                            host.download(filename,downloadtolocal)
                except:
                    print 'FTP ERROR'
            self._count+=1
        self._count=0

    def getinfo(self,info):
        self.ftpinfo = info

Solution

  • You are doing it wrong indeed.

    What you are doing now is that you call the run-method directly, but instead of that you should be calling start(), so the correct implementation should be:

    def Ftpstart(self):
        self.fp.start()
    

    When subclassing a QThread (or regular python thread for that matter), you implement the run-method, which represents the work the thread should be doing, and if you call it directly, you execute that code in the current thread (so in this case your main thread). This is why your GUI will become unresponsive.

    But if you call start() instead, it will actually spawn a new thread first (if it does not already exist) and then call run. From PyQT Documentation:

    QThread.start (self, Priority priority = QThread.InheritPriority)

    Begins execution of the thread by calling run(). The operating system will schedule the thread according to the priority parameter. If the thread is already running, this function does nothing.

    And for run()

    QThread.run (self)

    The starting point for the thread. After calling start(), the newly created thread calls this function.