在PySide2中优雅地关闭QThread

2024-09-29 21:43:03 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我正在使用PySide2编写一个应用程序,它将所有内容从stdout重定向到一个中间的queue.Queue。该Queue发出一个信号,将由QThread处理,将队列中的所有字符串附加到qtexted。你知道吗

我四处看了很多次,但不幸的是,似乎没有什么真正适合我。你知道吗

这就是我指的代码。你知道吗

from PySide2 import QtWidgets, QtGui, QtCore

import sys
from queue import Queue


class WriteStream(object):
    """ Redirects sys.stdout to a thread-safe Queue

    Arguments:
        object {object} -- base class
    """
    def __init__(self, queue):
        self.queue = queue

    def write(self, msg):
        self.queue.put(msg)

    def flush(self):
        """ Passing to create non-blocking stream (?!)
            https://docs.python.org/3/library/io.html#io.IOBase.flush
        """
        pass


class WriteStreamThread(QtCore.QThread):
    queue_updated = QtCore.Signal(str)

    def __init__(self, queue):
        super(WriteStreamThread, self).__init__()
        self.stop = False
        self.queue = queue

    def set_stop(self):
        self.stop = True
        self.wait() # waits till finished signal has been emitted

    def run(self):
        while not self.stop:    # i guess this is blocking
            msg = self.queue.get()
            self.queue_updated.emit(msg)
            self.sleep(1)   # if commented out, app crashes
        self.finished.emit()


class Verifyr(QtWidgets.QMainWindow):
    def __init__(self, queue, parent=None):
        super(Verifyr, self).__init__(parent)
        self.centralwidget = QtWidgets.QWidget(self)
        layout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.textedit = QtWidgets.QTextEdit(self)
        layout.addWidget(self.textedit)
        self.setLayout(layout)
        self.setCentralWidget(self.centralwidget)
        print("Verifyr initialised...")

        self.listener_thread = WriteStreamThread(queue)
        self.listener_thread.queue_updated.connect(self._log_to_qtextedit)
        self.listener_thread.start()

    @QtCore.Slot(str)
    def _log_to_qtextedit(self, msg):
        self.textedit.insertPlainText(msg)


if __name__ == '__main__':
    # create Queue to be passed to WriteStream and WriteStreamListener
    queue = Queue()
    # redirect stdout to WriteStream()
    sys.stdout = WriteStream(queue)
    print("Redirected sys.stdout to WriteStream")

    # launching the app
    app = QtWidgets.QApplication(sys.argv)
    window = Verifyr(queue)
    app.aboutToQuit.connect(window.listener_thread.set_stop)
    window.show()
    sys.exit(app.exec_())

WriteStreamThread中,我使用了一个while循环,它不断发出信号,由主应用程序捕获并附加到其qtexted。当我注释掉self.sleep(1)时,应用程序将陷入无限循环。如果没有,线程将退出刚刚好。你知道吗

谁能给我解释一下吗?你知道吗

更新: 正如我在评论中提到的,我发现了这个bug。。。以下是更新的run()方法WriteStreamThread

def run(self):
    while not self.stop:
        try:
            msg = self.queue.get(block=False) # nasty little kwarg
        except:
            msg = "No items in queue. Sleeping 1sec.."
            self.sleep(1)
        self.queue_updated.emit(msg)
    self.finished.emit()    # optional

Tags: toselfappqueueinitdefstdoutsys

热门问题