标题PyQt5开发之捕获控制台输出

**放在前面:**此文章非原创,参考了多份文章 在python中获取当前控制台输出
多线程
输出重定向至QTexeEdit

写这份文章的目的是为了自己方便查找。
如有侵权,请联系删除。

一、拟解决问题
在训练神经网络时,每个epoch的详细信息会出现在控制台上让我们查看,但是在开发软件时训练神经网络模型我们没办法看到控制台的输出信息,这时如果能够捕获print的打印信息,将其现在在多行文本编辑器里就可以解决了。

二、实行方案

1. stdout重定向

from io import StringIO		# 导入两个库
import sys
sys.stdout = buffer = StringIO()	# 将输出重定向至 变量buffer中
print("Hello World")				# 打印hello world ,这时无法看到打印的具体信息,因为打印信息存放在 buffer中,为了查看是否是这样的,我们改变输出重定向的位置,将输出信息保存在stdout.txt中
sys.stdout = open('./stdout.txt', 'a')	# 改变输出重定向位置
print(buffer.getvalue())	# buffer.getvalue()是获取buffer中的内容,字符串类型
print("Hello Python")		# 再打印 hello python

整个过程,PyCharm中的输出为空,
在这里插入图片描述
stdout.txt文件中的内容如下:
在这里插入图片描述
使用下面代码即可将输出的信息显示在QTextEdit中。

Mytext = QTextEdit(window)
Mytext.setText(buffer.getvalue())

存在问题:
无法实时获取打印信息

2. 重定向至QTextEdit

import sys
import time
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication, QTextEdit
class EmitStr(QObject):
    定义一个信号类,
    sys.stdout有个write方法,通过重定向,
    每当有新字符串输出时就会触发下面定义的write函数,
    进而发出信号
    text:新字符串,会通过信号传递出去
    textWrit  = pyqtSignal(str)
    def write(self, text):
        self.textWrit.emit(str(text))
class MyWidget(QWidget):    # 定义一个窗体类,继承于QWidget
    def __init__(self):
        super().__init__()
        self.step_up()      # 构建一个QTextEdit, 以及对窗体的一些基本设置
        sys.stdout = EmitStr(textWrit=self.outputWrite)     # 输出结果重定向
        sys.stderr = EmitStr(textWrit=self.outputWrite)     # 错误输出重定向
    def outputWrite(self, text):
        self.te.append(text)       # 输出的字符追加到 QTextEdit 中
    def step_up(self):
        self.setWindowTitle('输出重定向')
        self.resize(500,500)
        self.te = QTextEdit(self)
        self.te.move(10,10)
    def MyPrint(self):      # 定义个持续打印函数,用于验证
        for i in range(10):
            print(i)
            time.sleep(0.5)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.aboutToQuit.connect(app.deleteLater)
    w = MyWidget()
    w.show()
    w.MyPrint()
    sys.exit(app.exec())

现象:
界面出现假死现象,等待打印函数运行结束之后,才会把输出内容append到QTextEdit中。

3. 使用多线程
经过上面两步的操作,已将输出内容追加到QTextEdit中,对于界面假死现象,使用多线程处理,在线程中来运行比较耗时的程序,比如此时的模拟持续输出的打印函数。

关于多线程,只需用引入from PyQt5.Qt import QThread即可
只需用在下列代码中重新run()函数,即把比较耗时的代码放在run()中。
介绍QThread的两种方法:
start():启动线程
finished:线程结束时会发出信号

class MyThread(QThread):
    def __init__(self):
        super().__init__()
    def run(self):
        for i in range(10):
            print(i)
            time.sleep(0.5)

完整代码如下:

import sys
import time
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication, QTextEdit
from PyQt5.Qt import QThread
class EmitStr(QObject):
    定义一个信号类,
    sys.stdout有个write方法,通过重定向,
    每当有新字符串输出时就会触发下面定义的write函数,
    进而发出信号
    text:新字符串,会通过信号传递出去
    textWrit  = pyqtSignal(str)
    def write(self, text):
        self.textWrit.emit(str(text))
class MyWidget(QWidget):    # 定义一个窗体类,继承于QWidget
    def __init__(self):
        super().__init__()
        self.step_up()      # 构建一个QTextEdit, 以及对窗体的一些基本设置
        sys.stdout = EmitStr(textWrit=self.outputWrite)     # 输出结果重定向
        sys.stderr = EmitStr(textWrit=self.outputWrite)     # 错误输出重定向
    def outputWrite(self, text):
        self.te.append(text)       # 输出的字符追加到 QTextEdit 中
    def step_up(self):
        self.setWindowTitle('输出重定向')
        self.resize(500,500)
        self.te = QTextEdit(self)
        self.te.move(10,10)
class MyThread(QThread):
    def __init__(self):
        super().__init__()
    def run(self):
        for i in range(10):
            print(i)
            time.sleep(0.5)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.aboutToQuit.connect(app.deleteLater)
    w = MyWidget()
    mythread = MyThread()
    mythread.start()
    mythread.finished.connect(lambda: print('完成打印'))
    w.show()
    sys.exit(app.exec())
import sys
import qtawesome
from PyQt5.QtCore import QObject, pyqtSignal, QEventLoop, QTimer, QThread, QTime
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidget
                                    捕获控制台输出在 Python 开发中是一个非常重要的技能。本文介绍了多种方法来实现捕获控制台输出,包括重定向 sys.stdout 对象、使用 logging 模块、以及使用 subprocess 模块。这些技术可以帮助我们更好地管理和分析程序的输出。本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。
                                    一般情况下,程序运行结果在控制台输出,那如果不希望结果在控制台显示,而是输出到图形化用户界面呢?可以通过PyQt5,将运行结果输出定向到QTextEdit来完成。
环境:python3.7,pychram CE
1.准备工作
	PyQt5
Qt 5可以在官网下载,选择免费的OpenSource系列,但速度较慢。推荐在清华镜像下载Qt-5.13.0,整个软件较大,大概3.2G...
                                    当PyQt在代码中执行某些操作时,窗口通信和GUI交互将被阻塞。因此,需要用多线程的方式解决出现的视窗卡住的问题。本文完整代码实现:PyQt5多线程输出内容显示到窗口。
在QtDesigner中或者直接在py文件中写入一个相当于显示程序运行输出结果的文本框控件,例如textEdit,textBrowser。采用Pyqt中的信号机制,所有信息用信号发送出去,在用信号函数接收,连接槽函数再显示
写一个信号类,迎来发射标准输出作为信号:
class EmittingStr(QtCore.QObject):  
        textWritten = QtCore.pyqtSignal(str)  #定义一个发送str的信号
        def write(s
 5. 日志内容语法高亮 `PyQt5.Qsci`
 6. 日志具体信息弹窗*Dialog* (表单内容双击事件)
 7. logging Handler类,此程序可作为模块引入...
                                    Given this little snippet:import sysimport osimport loggingfrom PyQt5 import QtGui, QtWidgets, QtCorelog = logging.getLogger("Foo")logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(file...
        self.step_up=QWidget(self)#窗体类
        self.te = QTextEdit(self)#文本类
        sys.stdout = EmitStr(textWrit=self.outpu
                                    工作中为了方便调试,常常需要加入一些打印。常用 Qt 中的 QDebug / QWarning,C 和 C++ 中的 printf / cout 等等,又或者是三方库提供的标准打印接口。大部分时候,由于这些打印相当不统一(格式和位置),并且因为 Qt 作为 GUI 框架,调试信息实在不应该直接置于 UI 之上。接下来介绍一种能统一和标准化所有标准打印的方法( 所谓标准打印即标准输出 stdout 等),并且能够动态配置。