需要使用/as时执行线程的最佳方式(python、pyqt)

需要使用/as时执行线程的最佳方式(python、pyqt),python,pyqt,qthread,Python,Pyqt,Qthread,我正在尝试使用qthread运行worker类。如果使用workerObject=workerClass()实例化worker,我可以毫无问题地执行此操作。如果工人类需要始终执行退出操作,我该怎么做 下面是尝试这样做的示例代码。不幸的是,通过运行这个函数,exit函数无法执行,这很可能是因为线程不知道with/as语句 from PyQt4 import QtCore, QtGui from PyQt4.QtCore import QThread, QObject, pyqtSignal, py

我正在尝试使用qthread运行worker类。如果使用workerObject=workerClass()实例化worker,我可以毫无问题地执行此操作。如果工人类需要始终执行退出操作,我该怎么做

下面是尝试这样做的示例代码。不幸的是,通过运行这个函数,exit函数无法执行,这很可能是因为线程不知道with/as语句

from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import sys
import time

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(400, 284)
        self.textEdit = QtGui.QTextEdit(Dialog)
        self.textEdit.setGeometry(QtCore.QRect(20, 20, 361, 191))
        self.textEdit.setObjectName(_fromUtf8("textEdit"))
        self.pushButton = QtGui.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(170, 250, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.pushButton.setText(_translate("Dialog", "Print", None))



class UI_MainWindow(QtGui.QMainWindow, Ui_Dialog):
    def __init__(self, parent=None):
        super(UI_MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.run)


    def run(self):
        self.t = QThread()
        self.x = None
        with worker() as self.x:        
            self.x.signal.connect(self.write)
            self.x.moveToThread(t) 
            t.started.connect(self.x.run)
            t.start()

    @pyqtSlot(str)
    def write(self, text):
        self.textEdit.append("Running")
        qtObject.processEvents()




class worker(QObject):
    signal = pyqtSignal(str)

    def __init__(self, parent = None):
        super(worker, self).__init__(parent)

    def __enter__(self):
        return self

    def run(self):
        self.signal.emit("Running")
        time.wait(5)
        raise Exception

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            self.signal.emit("Exception")




def main(qtObject, guiObj):
    guiObj.show()
    qtObject.exec_()
    qtObject.processEvents()


qtObject = QtGui.QApplication(sys.argv)
guiObj = UI_MainWindow()
main(qtObject, guiObj)

LE:上下文涉及需要在QTextEdit窗口中打印来自worker类的任何失败消息。worker类执行期间引发的任何异常都会在其exit函数中进行处理,以便无论发生什么错误,脚本都会优雅地结束,为用户提供有意义的信息和指令。

函数
\uuuuuuuuuuuu
不会执行,问题是由于线程的非阻塞性,带有的
构造在工作进程“完成”并引发异常之前立即终止(调用
工作进程。_u退出__

实现所需功能的一种方法是使用
try/except
语句将代码包围在
worker.run()
中,以捕获任何未处理的异常并执行任何清理或发出信号

def run(self):
    try:
        self.signal.emit("Running")
        time.sleep(5)
        raise Exception
    except:
        self.signal.emit("Exception")

从user3419537解决方案开始,我最后给出了以下解决方案。第二个信号(statusSignal)用于将所有异常相关信息带回主类,以便调用exit函数

from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import sys
import time

class err(Exception):
    def __init__(self, *args):
        self.args = [a for a in args]

mainThread = QtCore.QThread.currentThread()

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(400, 284)
        self.textEdit = QtGui.QTextEdit(Dialog)
        self.textEdit.setGeometry(QtCore.QRect(20, 20, 361, 191))
        self.textEdit.setObjectName(_fromUtf8("textEdit"))
        self.pushButton = QtGui.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(170, 250, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.pushButton.setText(_translate("Dialog", "Print", None))



class UI_MainWindow(QtGui.QMainWindow, Ui_Dialog):
    def __init__(self, parent=None):
        super(UI_MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.run)

    def run(self):
        self.t = QThread()
        self.x = worker()          
        self.x.signal.connect(self.write)
        self.x.statusSignal.connect(self.runExit)
        self.x.moveToThread(self.t) 
        self.t.started.connect(self.x.run)
        self.t.start()

    @pyqtSlot(str)
    def write(self, text):
        self.textEdit.append(text)
        qtObject.processEvents()

    @pyqtSlot(object, object, object)
    def runExit(self, exc_type, exc_value, exc_traceback):
        self.t2 = QThread()
        self.x.moveToThread(self.t2)
        self.t2.started.connect(lambda: self.x.__exit__(exc_type, exc_value, exc_traceback))
        self.t2.start()






class worker(QObject):
    signal = pyqtSignal(str)
    statusSignal = pyqtSignal(object, object, object)

    def __init__(self, parent = None):
        super(worker, self).__init__(parent)

    def run(self):
        try:
            self.signal.emit("Run")
            time.sleep(2)
            self.moveToThread(mainThread)
            raise err("err message")
        except err:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            self.statusSignal.emit(exc_type, exc_value, exc_traceback)

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            self.signal.emit(exc_value.args[0])



def main(qtObject, guiObj):
    guiObj.show()
    qtObject.exec_()
    qtObject.processEvents()


qtObject = QtGui.QApplication(sys.argv)
guiObj = UI_MainWindow()
main(qtObject, guiObj)

最有可能的是,代码仍有一些调整,但就目前而言,它工作得非常完美。

我想知道,是否存在某种管道机制来强制使用/as来模拟uuu init uuuuu()、u enter uuuuu()、run()和uuu exit uuuuuuuu(),非常感谢!解决方案将退出操作替换为except中的操作,并执行该操作。尽管如此,我还是想知道是否有办法真正强制执行退出。同时,我已经开始播放另一个信号,该信号被设置为错误消息,每当发生这种情况时,UI_main窗口就会调用worker的exit函数。这可能是胡说八道,但我真的需要那个出口才能被处决。我需要弄清楚的一件事是如何设置exc_类型、exc_值和回溯。我想这些家伙一定是在第二个信号的错误消息中设置的。正如我所解释的,
\uuuuuu exit\uuuu
正在执行。您可以通过在开头插入
print
语句来验证这一点。但是,它不会在您期望的时候被调用,并且不会发出异常信号。您试图从
\uuuuu exit\uuuu
函数中执行哪些在异常处理程序中无法执行的操作?