QPlainTextEdit:使用线程的子进程分段错误

时间:2018-07-10 19:03:38

标签: python pyqt segmentation-fault subprocess pyside

在QPlainTextEdit上显示时subprocess.stdout中的分段错误

嗨, 我正在启动显示函数的线程,并将其结果流式传输到线程中的QTextEdit对象。由于未知原因,该函数有时会因分段错误而崩溃。

self.plainTextEdit = QPlainTextEdit()
self.thread = Thread(target = runcmd, args = ("make dc",))
self.thread.start()
self.thread.join()
def runcmd(self,cmd):
    process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE, bufsize=-1)
    while True:
        line = process.stdout.readline()
        if not line:
            break
        self.plainTextEdit.moveCursor(QTextCursor.End)
        self.plainTextEdit.insertPlainText(line.strip())
    process.terminate()

  

制作直流电

命令是对设计编译器综合工具的调用。如果我尝试打印

  

变量,而不是写入plainTextEdit对象,线程运行良好,在终端窗口中显示结果。欢迎任何帮助/建议...... 谢谢

3 个答案:

答案 0 :(得分:0)

您不能从python线程使用QT东西。您的选择:

  • 使用queue.Queue或其他类似的同步对象,将数据从线程发送回主程序。然后,主程序将数据添加到文本小部件。 Documentation here.
  • 使用QThread,与线程的QT等效。 Documentation here

答案 1 :(得分:0)

您不能从另一个线程更新Qt GUI。对于我们来说幸运的是,Qt给了我们信号,而PyQt给了我们pyqtSignal,仅用于这种情况。有几种方法可以做到,但是我更喜欢以下样式。

class YourClass(QtCore.QObject):
    appendSignal = pyqtSignal(str)
    def __init__(self):
        super(YourClass, self).__init__()
        self.plainTextEdit = QPlainTextEdit()
        self.appendSignal.connect(self.reallyAppendToTextEdit)
        self.appendToTextEdit = self.appendSignal.emit
        self.thread = Thread(target = runcmd, args = ("make dc",))
        self.thread.start()
        self.thread.join()
    def reallyAppendToTextEdit(self, txt):
        self.plainTextEdit.moveCursor(QTextCursor.End)
        self.plainTextEdit.insertPlainText(txt)
    def runcmd(self,cmd):
        process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE, bufsize=-1)
        while True:
            line = process.stdout.readline()
            if not line:
                break
            self.appendToTextEdit(line.strip())
        process.terminate()

答案 2 :(得分:0)

您应该使用GUI友好的subprocess.Popen()而不是使用QProcess,因此不必使用新线程。

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

import shlex


class LogWidget(QWidget):
    def __init__(self, parent=None):
        super(LogWidget, self).__init__(parent)
        lay = QVBoxLayout(self)
        self.plainTextEdit = QPlainTextEdit()
        lay.addWidget(self.plainTextEdit)
        self.runcmd("make dc")

    def runcmd(self, cmd):
        process = QProcess(self)
        process.readyReadStandardOutput.connect(self.onReadyReadStandardOutput)
        process.readyReadStandardError.connect(self.onReadyReadStandardError)
        program, *arguments = shlex.split(cmd)
        process.start(program, arguments)

    def onReadyReadStandardOutput(self):
        process = self.sender()
        self.plainTextEdit.appendPlainText(str(process.readAllStandardOutput()))

    def onReadyReadStandardError(self):
        process = self.sender()
        self.plainTextEdit.appendPlainText(str(process.readAllStandardError()))


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    w = LogWidget()
    w.show()
    sys.exit(app.exec_())