从辅助线程重定向标准输出(使用函数而不是类进行多线程处理?) [英] Redirecting stdout from a secondary thread (multithreading with a function instead of class?)

查看:135
本文介绍了从辅助线程重定向标准输出(使用函数而不是类进行多线程处理?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将我的stdout显示在通过Qt Designer(PyQt5)制作的QTextEdit上.实际上我使它工作了,但它并没有在制作的同时显示信息.相反,它等待过程完全结束,然后才立即显示所有信息.我了解这应该通过线程解决.另外,由于QTextEdit(本身)是一个GUI元素,因此我需要一种不同的方法.我在这里找到了想要的答案:

I am trying to get my stdout displayed on a QTextEdit made via Qt Designer (PyQt5). Actually I made it work yet it doesn't show the info at the same time it was made. Instead it waits for the process to completely end and only then it shows all the information at once. I understand that this should be solved via threading. Also since the QTextEdit (itself) is a GUI element i need a different approach. I found the answer I was looking for here:

此问题参考: 将stdout和stderr重定向到PyQt4 QTextEdit从辅助线程

@three_pineapples提供了答案.

@three_pineapples provided the answer.

我的问题几乎完全相同,因此答案也是正确的.但是我的情况有些不同,我无法使其正常工作.

My question is pretty much exactly the same, thus the answer is also correct. But my scenario is a little different and I'm having trouble making it work.

在所有线程回答中,我仅使用类看到它们.但是事情是在我的主类中,我有一个函数可以执行将要打印在QTextEdit上的所有内容.有时需要几分钟才能完成.我正在寻找一种使用@three_pineapples提供的答案的以下示例代码的方法.

In all the threading answers I only see them using Classes. But the thing is in my main class I have a function that does all the stuff that would be printed on the QTextEdit. Sometimes it takes minutes to complete. I am looking for a way for the example code below to work using the answer provided by @three_pineapples.

这是示例代码:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtGui import QTextCursor

from ui_form import Ui_Form


class EmittingStream(QObject):  # test
    textWritten = pyqtSignal(str)

    def write(self, text):
        self.textWritten.emit(str(text))


class Form(QMainWindow):

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

        # Install the custom output stream
        sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)  # test

        self.ui = Ui_Form()
        self.ui.setupUi(self)

        self.ui.pushButton_text.clicked.connect(self.test_write)

    def __del__(self):  # test
        # Restore sys.stdout
        sys.stdout = sys.__stdout__

    def normalOutputWritten(self, text):  # test
        """Append text to the QTextEdit."""
        cursor = self.ui.textEdit.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.ui.textEdit.setTextCursor(cursor)
        self.ui.textEdit.ensureCursorVisible()

    def test_write(self):  # this is a long, complicated function. its nested in this class. I don't have a way to get it out as a different class.
        print("something written")


def main():
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

有没有办法让提供的解决方案直接在主类的(test_write)函数上工作?我将如何实施?

Is there a way to get the provided solution to work -directly- on the (test_write) function in my main class? How would I implement it?

更清楚地说,从参考链接"LongRunningThing"类对我不可用.需要在单独的线程上运行的函数在主类(在示例代码中名为Form())内.也许可以使用嵌套的类将test_write函数封装在我的主类中?那有可能吗?

To make it more clear, from the reference link "LongRunningThing" class is not available for me. The function that needs to run on a separate thread is within the main class (named Form() in the example code). Perhaps a nested class could be used that encapsulates the test_write function inside my main class? Is that even possible?

推荐答案

在这种情况下,您可以使用python的本机threading:

For this case you can use the native threading of python:

import sys

import threading
import time

from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtGui import QTextCursor

from ui_form import Ui_Form


class EmittingStream(QObject):  # test
    textWritten = pyqtSignal(str)

    def write(self, text):
        self.textWritten.emit(str(text))


class Form(QMainWindow):
    finished = pyqtSignal()
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        # Install the custom output stream
        sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)  # test

        self.ui = Ui_Form()
        self.ui.setupUi(self)

        self.ui.pushButton_text.clicked.connect(self.start_task)
        self.finished.connect(lambda: self.ui.pushButton_text.setEnabled(True))

    def start_task(self):
        var = self.ui.lineEdit.text()
        self.thread = threading.Thread(target=self.test_write, args=(args, ))
        self.thread.start()
        self.ui.pushButton_text.setEnabled(False)

    def __del__(self):  # test
        # Restore sys.stdout
        sys.stdout = sys.__stdout__

    def normalOutputWritten(self, text):  # test
        """Append text to the QTextEdit."""
        cursor = self.ui.textEdit.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.ui.textEdit.setTextCursor(cursor)
        self.ui.textEdit.ensureCursorVisible()

    def test_write(self, *args):
        var1 = args[0]
        print("something written")
        time.sleep(5) # simulate expensive task
        print("something written ----")
        self.finished.emit()


def main():
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

这篇关于从辅助线程重定向标准输出(使用函数而不是类进行多线程处理?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆