【问题标题】:Redirect console output to pyqt5 gui in real time实时将控制台输出重定向到 pyqt5 gui
【发布时间】:2021-04-28 09:29:06
【问题描述】:

我想使用 PyQt5 在 gui 中实时重定向 python 程序的控制台输出

我的意思是,在 python 程序执行的每个输出中,gui 都会立即显示此输出

我使用的代码只在完成整个程序后显示日志,并没有解决实时问题

你能帮我吗

在我的代码下面:

from PyQt5 import QtGui,QtCore
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

class gui(QMainWindow):
    def __init__(self):
        super(gui, self).__init__()
        self.initUI()

    def dataReady(self):
        cursor = self.output.textCursor()
        cursor.movePosition(cursor.End)
        cursor.insertText(str(self.process.readAll()))
        self.output.ensureCursorVisible()

    def callProgram(self):
        # run the process
        # `start` takes the exec and a list of arguments
        self.process.start('python',['Robot.py'])

    def initUI(self):
        # Layout are better for placing widgets
        layout =  QHBoxLayout()
        self.runButton =  QPushButton('Run')
        self.runButton.clicked.connect(self.callProgram)

        self.output =  QTextEdit()
        self.setGeometry(100, 60, 1000, 800)
        layout.addWidget(self.output)
        layout.addWidget(self.runButton)

        centralWidget =  QWidget()
        centralWidget.setLayout(layout)
        self.setCentralWidget(centralWidget)

        # QProcess object for external app
        self.process = QtCore.QProcess(self)
        # QProcess emits `readyRead` when there is data to be read
        self.process.readyRead.connect(self.dataReady)

        # Just to prevent accidentally running multiple times
        # Disable the button when process starts, and enable it when it finishes
        self.process.started.connect(lambda: self.runButton.setEnabled(False))
        self.process.finished.connect(lambda: self.runButton.setEnabled(True))


#Function Main Start
def main():
    app =QApplication(sys.argv)
    ui=gui()
    ui.show()
    sys.exit(app.exec_())
#Function Main END

if __name__ == '__main__':
    main() ```

【问题讨论】:

  • 您可以启动一个线程来处理时间循环中的更新,或者使用信号之类的中断来处理异步事件。

标签: python logging pyqt pyqt5


【解决方案1】:

当您将 python 输出重定向到文件或管道时,出于性能原因,它会被缓冲。您需要使用-u cli 参数运行脚本刷新每个打印输出,如下所示:print(something, flush=True)。详情请见this question

self.process.start('python',['-u','Robot.py'])

【讨论】:

  • 谢谢。 self.process.start('python',['-u','Robot.py']) 为我工作......但每一行都与下一行与'\ n'相结合。你知道有什么解决办法有独立的线吗?
  • strip() 插入前的文字?
  • 我不明白,我希望每个输出都在一个独立的行中,我的意思是我将 '\n' 替换为有效返回到下一行
  • @Patrick 使用 cursor.insertText(self.process.readAll().data().decode())
【解决方案2】:

这里的完整解决方案,感谢@mugiseybrows 和@eyllanesc

它解决了两个问题:第一个是在 gui 中重定向 python 程序的输出,第二个是在一个独立的行中显示每个输出

import sys
from PyQt5 import QtGui,QtCore
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

class gui(QMainWindow):
    def __init__(self):
        super(gui, self).__init__()
        self.initUI()

    def dataReady(self):
        cursor = self.output.textCursor()
        cursor.movePosition(cursor.End)
        #cursor.insertText(str(self.process.readAll()))
        cursor.insertText(self.process.readAll().data().decode())
        self.output.ensureCursorVisible()

    def callProgram(self):
        # run the process
        # `start` takes the exec and a list of arguments
        self.process.start('python',['-u','Robot.py'])

    def initUI(self):
        # Layout are better for placing widgets
        layout =  QHBoxLayout()
        self.runButton =  QPushButton('Run')
        self.runButton.clicked.connect(self.callProgram)

        self.output =  QTextEdit()
        self.setGeometry(100, 60, 1000, 800)
        layout.addWidget(self.output)
        layout.addWidget(self.runButton)

        centralWidget =  QWidget()
        centralWidget.setLayout(layout)
        self.setCentralWidget(centralWidget)

        # QProcess object for external app
        self.process = QtCore.QProcess(self)
        # QProcess emits `readyRead` when there is data to be read
        self.process.readyRead.connect(self.dataReady)

        # Just to prevent accidentally running multiple times
        # Disable the button when process starts, and enable it when it finishes
        self.process.started.connect(lambda: self.runButton.setEnabled(False))
        self.process.finished.connect(lambda: self.runButton.setEnabled(True))


#Function Main Start
def main():
    app =QApplication(sys.argv)
    ui=gui()
    ui.show()
    sys.exit(app.exec_())
#Function Main END

if __name__ == '__main__':
    main() 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 2013-11-14
    • 2020-11-16
    • 2010-10-08
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多