如何让 QThreads 在控制台 PySide 程序中工作?

Posted

技术标签:

【中文标题】如何让 QThreads 在控制台 PySide 程序中工作?【英文标题】:How to get QThreads to work in a console PySide program? 【发布时间】:2012-04-06 13:32:09 【问题描述】:

我正在尝试学习如何在 python 程序中使用线程。我正在使用 PySide 和 QThreads,因为之后我将使用 PySide 实现 gui。

至少我认为我已经理解了线程的主要概念。但我仍然对事件循环感到困惑。我认为这是我的应用程序的问题。

这是一个我无法正常工作的示例应用程序。 在我的主类中,我有几个工作线程,我希望他们向主类报告他们的进度。但是主程序不会实时打印进度信息。

我怎样才能让它工作?

from PySide import QtCore
import time, sys

class MyWorkerThread(QtCore.QThread):
    message = QtCore.Signal(str)

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

    def run(self):
        for i in range(10):
            self.message.emit("%d: %d" % (self.id, i))
            time.sleep(0.2)

class MainProgram():
    def __init__(self, parent=None):
        self.threads = []

        self.addWorker(MyWorkerThread(1))
        self.addWorker(MyWorkerThread(2))

    def addWorker(self, worker):
        worker.message.connect(self.printMessage, QtCore.Qt.QueuedConnection)
        self.threads.append(worker)

    def startWorkers(self):
        for worker in self.threads:
            worker.start()
            worker.wait()
        self.workersFinished()

    def workersFinished(self):
        QtCore.QCoreApplication.instance().quit()

    @QtCore.Slot(str)
    def printMessage(self, text):
        sys.stdout.write(text+'\n')
        sys.stdout.flush()

if __name__ == '__main__':
    app = QtCore.QCoreApplication(sys.argv)
    m = MainProgram()
    m.startWorkers()
    sys.exit(app.exec_())

【问题讨论】:

实时是什么意思?你应该在调用wait() 之前启动所有线程。您正在开始一个,等待它完成然后开始下一个。 程序在工作循环期间不打印任何内容。但它会在两个线程完成后同时打印所有消息。在此之后,程序不会自行关闭。我将有几百名这些工人,他们的过程非常密集。所以实际上我什至不希望那些在这一点上并行运行。也许以后我会改变这个,这样几个线程并行运行。 【参考方案1】:

worker.wait() 是问题所在。此调用会阻塞主线程(在本例中为一个正在运行的事件循环),直到 worker 完成其工作。

这是一个稍有改动的版本(我已经评论了我的改动):

from PySide import QtCore
import time, sys

class MyWorkerThread(QtCore.QThread):
    message = QtCore.Signal(str)

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

    def run(self):
        for i in range(10):
            self.message.emit("%d: %d" % (self.id, i))
            time.sleep(0.2)

class MainProgram():
    def __init__(self, parent=None):
        self.threads = []

        self.addWorker(MyWorkerThread(1))
        self.addWorker(MyWorkerThread(2))

    def addWorker(self, worker):
        worker.message.connect(self.printMessage, QtCore.Qt.QueuedConnection)
        # connect the finished signal to method so that we are notified
        worker.finished.connect(self.workersFinished)
        self.threads.append(worker)

    def startWorkers(self):
        for worker in self.threads:
            worker.start()
            # no wait, no finished. you start the threads and leave.

    def workersFinished(self):
        if all(worker.isFinished() for worker in self.threads):
            # wait until all the threads finished
            QtCore.QCoreApplication.instance().quit()

    @QtCore.Slot(str)
    def printMessage(self, text):
        sys.stdout.write(text+'\n')
        sys.stdout.flush()

if __name__ == '__main__':
    app = QtCore.QCoreApplication(sys.argv)
    m = MainProgram()
    m.startWorkers()
    sys.exit(app.exec_())

【讨论】:

谢谢,帮了大忙。

以上是关于如何让 QThreads 在控制台 PySide 程序中工作?的主要内容,如果未能解决你的问题,请参考以下文章

PySide 如何在 python 控制台中查看 QML 错误?

一起使用 psycopg2 和 Qthreads(或者只是 postgresql 和 qthreads)并更新 GUI

PySide2 和 Matplotlib:如何让 MatPlotLib 在单独的进程中运行? ..因为它不能在单独的线程中运行

如何确保 QApplication 及其 QThreads 全部关闭

如何使用 PySide 控制 QML UI?

如何在 Windows 上安装 PySide 的步骤