【问题标题】:How to get exe stdout in real time in GUI though cmd is executing in Python? [duplicate]尽管 cmd 在 Python 中执行,如何在 GUI 中实时获取 exe 标准输出? [复制]
【发布时间】:2021-03-25 10:00:09
【问题描述】:
with Popen([cmd command], stdout=PIPE, bufsize=1, 
    universal_newlines=True) as p:
    for line in p.stdout:
        log.insertPlainText(line)

我想通过Python代码运行exe文件,实时从pyqt获取打印内容。所以我写了上面的代码。但是,在cmd中打印的所有结果都执行完之后,exe内容一下子打印出来了。即使 cmd 仍在工作,我也想在 GUI 中实时接收它,而不是在执行完 cmd 的所有内容后将其输出到 pyqt。我想要一个参数值或其他方法来解决这个问题。

【问题讨论】:

  • 如果您想逐行处理exe的输出或其他内容,我仍然有点不清楚。我(似乎)理解的是,您可以一次获得所有输出。这是正确的吗?
  • @Wolf 我已经单独实现了 pyqt GUI,并且我为所有操作创建了一个单独的 python 文件。你知道如何让它作为 Python 文件而不是在 GUI 上工作吗?
  • 也许用print(line)import subprocess 替换log.insertPlainText(line) 和显示块之前的import subprocess。您可能能够以交互方式检查行为。
  • @Wolf 我已经检查了 print(line) 结果输出是否正确,但我希望 exe 的输出被视为 GUI 上的日志,而不是 cmd 的输出。这就是我使用 log.insertPlainText 的原因。
  • print(line)的时候,结果是从cmd实时输出的(所以我用了'properly'这个词),但问题是log .insertPlaintext(line) 结果不会在 GUI 上实时输出。

标签: python pyqt


【解决方案1】:

QtCore.QProcess 具有 readyReadStandardErrorreadyReadStandardOutput 信号,它们在标准输出和标准错误准备就绪时发出数据

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt

def buffer_to_str(buf):
    codec = QtCore.QTextCodec.codecForName("UTF-8")
    return str(codec.toUnicode(buf))

class Process(QtCore.QObject):

    stdout = QtCore.pyqtSignal(str)
    stderr = QtCore.pyqtSignal(str)
    finished = QtCore.pyqtSignal(int)

    def start(self, program, args):
        process = QtCore.QProcess()
        process.setProgram(program)
        process.setArguments(args)
        process.readyReadStandardError.connect(lambda: self.stderr.emit(buffer_to_str(process.readAllStandardError())))
        process.readyReadStandardOutput.connect(lambda: self.stderr.emit(buffer_to_str(process.readAllStandardOutput())))
        process.finished.connect(self.finished)
        process.start()
        
        self._process = process

if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    process = Process()
    
    log = QtWidgets.QPlainTextEdit()
    log.show()
    
    process.stderr.connect(log.appendPlainText)

    cmd = "ping"
    args = ["google.com"]
    process.start(cmd, args)

    app.exec_()

【讨论】:

  • 有趣的方法可能是 OP 的最佳解决方案。您可能知道为什么会出现 OP 描述的问题吗?
  • @Wolf 我相信python子进程只能以阻塞方式同步读取,这不允许它在主gui线程中使用,你必须将它移动到QThread或者只是使用QtCore.QProcess。 OP 可以尝试asyncio python 模块,不过我不知道如何将它与 gui 混合。
  • 啊,好像是这样的。我不确定Popen 是否为此创建了一个单独的线程。
猜你喜欢
  • 2016-02-15
  • 2021-11-01
  • 2013-09-15
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
  • 2019-12-20
相关资源
最近更新 更多