无法将pyqtSignal与pyQtSlot连接 - PyQt5和Python 3.5

时间:2017-05-11 00:55:29

标签: python python-3.x pyqt pyqt5 qthread

尝试使用QThread和PyQt5的插槽/信号来处理后台线程中的多个文件。

我在PyQt5.8.2中使用Python 3.5.2。 PyCharm 2017.1给了我警告:

  • # FAILS HERE的{​​{1}}部分的Unresolved attribute referenceconnect
  • {li>和w.done.connect(..)代表Cannot find reference 'connect' in 'function'

当我尝试在PyCharm之外跑步时,我得到thread.started.connect(...)。 在PyCharm中查看完成标签时,没有显示TypeError: decorated slot has no signature compatible with Worker.done[]connect()方法,但disconnect()确实如此。 所有关于SO的教程和问题都说下面应该有效。

简化代码是:

emit()

更新:我最终通过卸载pyqt5并从此处重新安装(anaconda.org/bpentz/pyqt5)来解决此问题。我不知道这是如何解决这个问题的,但确实如此。但是,此代码不起作用,它几乎立即关闭QThread()。我更新了以下相关代码(下面),现在我在终端或PyCharm中得到了没有Traceback的python崩溃(奇怪的是,这在调试器中工作得很好)。目标是循环遍历文件并在多个QThreads()中处理它们,更新进度条(update_this),然后在处理完所有文件时提醒用户。

from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QThread
from PyQt5.QtWidgets import QMainWindow

class MyApp(QMainWindow, myUiMainWindow):

    def __init__(self):
        super(self.__class__, self).__init()
        self.setupUI(self)

    @pyqtSlot()
    def update_this(self):
        <update things>

    def doMyStuff(self):
        <get a file_list>
        for f in file_list:
            w = Worker(f)
            thread = QThread()
            w.moveToThread(thread)
            w.done.connect(self.update_this)       # FAILS HERE
            thread.started.connect(w.process)      # FAILS HERE
            thread.start()

class Worker(QObject):
    done = pyqtSignal()
    def __init__(self, file_path):
        super(Worker, self).__init__(parent=None)
        self.f = file_path

    @pyqtSlot()
    def process(self):
        <do stuff>
        self.done.emit()

额外更新:如前所述,问题不在于将工作者留在内存中。完成此操作后,线程方案即可运行。然而,同样如上所述,使用QThread()并没有实现我正在寻找的多处理效率的想法,并且认为QThreading可能会实现,并且比仅仅在单个QThread()中串行处理文件更糟糕。尝试使用多重处理会导致其他问题here

使用QThread()代码(虽然很慢!):

from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QThread
from PyQt5.QtWidgets import QMainWindow

        class MyApp(QMainWindow, myUiMainWindow):

            def __init__(self):
                super(self.__class__, self).__init()
                self.setupUI(self)
                self.pushButton.clicked.connect(self.doMyStuff)

            @pyqtSlot()
            def thread_complete(self):
                self.num_completed += 1
                if self.num_completed == len(self.file_list):
                    <reset things>

            def doMyStuff(self):
            <get a self.file_list>
            self.num_completed = 0
            self.threads = []
            for f in self.file_list:
                w = Worker(f)
                self.threads.append(QThread())
                w.moveToThread(threads[-1])       
                self.threads[-1].started.connect(w.process)  
                self.threads[-1].finished.connect(self.thread_complete)    
                self.threads[-1].start()

        class Worker(QObject):
            def __init__(self, file_path):
                super(Worker, self).__init__(parent=None)
                self.f = file_path

            @pyqtSlot()
            def process(self):
                <do stuff with self.f>

1 个答案:

答案 0 :(得分:-2)

你应该直接将QThread子类化

class WorkerThread(QThread):
    def __init__(self, data):
        super(WorkerThread, self).__init__()
        self.setTerminationEnabled(True)
        self.start()

    def run(self):
        pass
        #do work here

你可以将一个插槽连接到这个对象,线程发出&#34;完成&#34;

 myworker = WorkerThread(data)
 myworker.finished.connect(doWhatYouWant)