另一个python子进程实时监视stdout

时间:2017-06-15 18:51:06

标签: windows python-3.x subprocess

我知道我正在问另一个关于这个话题的问题,所以我必须密集。我无法获得以下代码示例来显示长时间运行的子进程在其运行时的输出(实时)。代码工作,线程启动,子进程执行,但所有输出仅在子进程退出后显示。它挂起在line = self.proc.stdout.readline()行,直到子进程完成。

这是我的第一个Python应用程序,我使用Python 3.6在Windows上运行它。我已经阅读了尽可能多的子流程答案,我已经阅读了子流程源代码和文档,但是当所有答案都说它应该时,我无法使其工作。我没有得到这个概念的哪一部分?

#! python

import sys
import os
import subprocess
import shlex
from threading import Thread

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

##############################################################
class ExternalProc(QDialog):

    outputUpdate = pyqtSignal(str)
    procFinished = pyqtSignal()

    def __init__(self, parent):
        super(ExternalProc, self).__init__(parent)

        self.procFinished.connect(self.stop)

        vbox = QVBoxLayout(self)

        grpBoxLayout = QVBoxLayout()
        outputTextGrpBox = QGroupBox("Process Output")        

        self.outputText = QTextEdit(outputTextGrpBox)
        self.outputText.setReadOnly(True)
        self.outputText.setLineWrapMode(QTextEdit.NoWrap)
        grpBoxLayout.addWidget(self.outputText, 1)
        outputTextGrpBox.setLayout(grpBoxLayout)

        vbox.addWidget(outputTextGrpBox)

        self.setLayout(vbox)
        self.outputUpdate.connect(self.AppendOutput)
        self.setWindowTitle("Process Output")
        self.show()

    def AppendOutput(self, str):
        self.outputText.append(str)
        QApplication.processEvents()

    def runProc(self):
        self.proc = subprocess.Popen(self.command, bufsize=1, universal_newlines=True,  
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        while self.proc.poll() is None:
            line = self.proc.stdout.readline()
            self.outputUpdate.emit(line.rstrip())

        #for line in iter(self.proc.stdout.readline, ""):
        #    self.outputUpdate.emit(line.rstrip())

        self.procFinished.emit()
        print("debug: proc thread stopping")

    def start(self, cmd):
        self.command = cmd
        self.procThread = Thread(target=self.runProc)
        self.procThread.start()
        print("debug: proc thread started")

    def stop(self):
        self.proc.stdout.close()
        self.procThread.join()
        print("debug: proc thread stopped")

##############################################################
class LaunchProc(QWidget):

    def __init__(self):
        super().__init__()

        vbox = QVBoxLayout(self)

        cmdGrpBox = QGroupBox("Process Command", self)
        hbox = QHBoxLayout(self)

        cmdLabel = QLabel("Command:", cmdGrpBox)
        cmdLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        hbox.addWidget(cmdLabel)

        self.cmdText = QLineEdit(cmdGrpBox)
        hbox.addWidget(self.cmdText, 1)

        cmdBtn = QPushButton("Launch", cmdGrpBox)
        cmdBtn.setDefault(True)
        cmdBtn.clicked.connect(self.launchCmd)
        hbox.addWidget(cmdBtn)

        cmdGrpBox.setLayout(hbox)

        vbox.addWidget(cmdGrpBox)
        vbox.addStretch()
        self.setLayout(vbox)

        self.setWindowTitle("Long Running Process")
        self.center()

        self.show()

    def center(self):        
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def launchCmd(self):
        launchDlg = ExternalProc(self)
        args = shlex.split(self.cmdText.text())
        launchDlg.start(args)

##############################################################
if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = LaunchProc()
    sys.exit(app.exec_())

0 个答案:

没有答案