【问题标题】:QPlainTextEdit: subprocess segmentation fault using threadsQPlainTextEdit:使用线程的子进程分段错误
【发布时间】:2018-07-10 19:03:38
【问题描述】:

在 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()

制作直流

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

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

【问题讨论】:

    标签: python pyqt segmentation-fault subprocess pyside


    【解决方案1】:

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

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

    【讨论】:

    • 我尝试使用 QThread ...但结果相同... :(
    • 它不是 直接替换 @DhanushSrinivasa - 您必须在 QThreads 之间移动对象 - 阅读链接文档。
    【解决方案2】:

    您不能从另一个线程更新 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()
    

    【讨论】:

      【解决方案3】:

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

      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_())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-29
        • 2016-03-23
        • 1970-01-01
        • 2018-04-25
        • 2022-01-10
        • 1970-01-01
        相关资源
        最近更新 更多