Python 用于获取标准输出的 PyQt5 信号不起作用
Python PyQt5 signal for getting stdout not working
我遇到了一个很奇怪的错误。
我正在尝试将 QProcess 输出重定向到 textbrowser.append()
在调试模式下,它在 VS 和 VSCode 中工作,但在发布模式下不起作用。
信号 readyReadStandardError 和 readyReadStandardOut 在此过程中不发出信号。只有当它完成时。
但是我需要它在这个过程中发出信号。
我已经试过了
- 寻找通道中的问题(setProcessChannelMode(QtCore.QProcess.ForwardedOutputChannel)正在工作并实时打印到 main.sys。stdout 但我只需要 stdout从 Qprocess 传输到 QtextBrowser。当我将频道切换到 SeparateChannels 或 MergedChannels 时,我没有输出。
- 尝试了不同的信号方法(-started()、-errorOccured())
我的代码看起来像这样:
self.process = QtCore.QProcess()
self.process.setProgram("python")
self.process.setArguments(["run.py"])
#both not working when no debugging mode in VSCode
#self.process.readyReadStandardError.connect(self.on_readyReadStandardError)
#self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
#ForwardedOutputChannel is working
self.process.setProcessChannelMode(QtCore.QProcess.ForwardedOutputChannel)
#another try not working
#self.process.setReadChannel(QtCore.QProcess.StandardOutput)
#tried here a different signal with no luck
#self.process.started.connect(self.on_readyReadStandardOutput)
self.pushButton.clicked.connect(self.accepted)
#starting process on button click
def accepted(self):
self.process.start()
#what to do when readyReadStandardOutput signal is emitted - i did the same for stderr
def on_readyReadStandardOutput(self):
print("hi") #test if the signal is being send
out = self.processSubscribe.readAllStandardOutput().data().decode().strip()
self.textBrowser.append(out)
编辑
这里有一小段测试:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setObjectName("textBrowser")
self.gridLayout.addWidget(self.textBrowser, 1, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.process = QtCore.QProcess()
self.process.setProgram("python")
self.process.setArguments(["[INPUT PATH TO FILE]\run.py"])
#both not working when no debugging mode in VSCode
self.process.readyReadStandardError.connect(self.on_readyReadStandardError)
self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
#ForwardedOutputChannel is working
#self.process.setProcessChannelMode(QtCore.QProcess.ForwardedOutputChannel)
self.pushButton.clicked.connect(self.accepted)
#starting process on button click
def accepted(self):
self.process.start()
#what to do when readyReadStandardOutput signal is emitted - i did the same for stderr
def on_readyReadStandardOutput(self):
print("hi") #test if the signal is being send
out = self.process.readAllStandardOutput().data().decode().strip()
self.textBrowser.append(out)
def on_readyReadStandardError(self):
err = self.process.readAllStandardError().data().decode().strip()
self.textBrowser.append(err)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
run.py 看起来像这样(QProcess 的外部 python 程序)
import time
for i in range(5):
print(i)
time.sleep(1)
自己复制试试
我找到了正确的答案。
我编辑 run.py 行
sys.stdout.flush()
所以:
import time
for i in range(5):
print(i)
sys.stdout.flush()
time.sleep(1)
我遇到了一个很奇怪的错误。 我正在尝试将 QProcess 输出重定向到 textbrowser.append() 在调试模式下,它在 VS 和 VSCode 中工作,但在发布模式下不起作用。 信号 readyReadStandardError 和 readyReadStandardOut 在此过程中不发出信号。只有当它完成时。 但是我需要它在这个过程中发出信号。
我已经试过了
- 寻找通道中的问题(setProcessChannelMode(QtCore.QProcess.ForwardedOutputChannel)正在工作并实时打印到 main.sys。stdout 但我只需要 stdout从 Qprocess 传输到 QtextBrowser。当我将频道切换到 SeparateChannels 或 MergedChannels 时,我没有输出。
- 尝试了不同的信号方法(-started()、-errorOccured())
我的代码看起来像这样:
self.process = QtCore.QProcess()
self.process.setProgram("python")
self.process.setArguments(["run.py"])
#both not working when no debugging mode in VSCode
#self.process.readyReadStandardError.connect(self.on_readyReadStandardError)
#self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
#ForwardedOutputChannel is working
self.process.setProcessChannelMode(QtCore.QProcess.ForwardedOutputChannel)
#another try not working
#self.process.setReadChannel(QtCore.QProcess.StandardOutput)
#tried here a different signal with no luck
#self.process.started.connect(self.on_readyReadStandardOutput)
self.pushButton.clicked.connect(self.accepted)
#starting process on button click
def accepted(self):
self.process.start()
#what to do when readyReadStandardOutput signal is emitted - i did the same for stderr
def on_readyReadStandardOutput(self):
print("hi") #test if the signal is being send
out = self.processSubscribe.readAllStandardOutput().data().decode().strip()
self.textBrowser.append(out)
编辑 这里有一小段测试:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setObjectName("textBrowser")
self.gridLayout.addWidget(self.textBrowser, 1, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.process = QtCore.QProcess()
self.process.setProgram("python")
self.process.setArguments(["[INPUT PATH TO FILE]\run.py"])
#both not working when no debugging mode in VSCode
self.process.readyReadStandardError.connect(self.on_readyReadStandardError)
self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
#ForwardedOutputChannel is working
#self.process.setProcessChannelMode(QtCore.QProcess.ForwardedOutputChannel)
self.pushButton.clicked.connect(self.accepted)
#starting process on button click
def accepted(self):
self.process.start()
#what to do when readyReadStandardOutput signal is emitted - i did the same for stderr
def on_readyReadStandardOutput(self):
print("hi") #test if the signal is being send
out = self.process.readAllStandardOutput().data().decode().strip()
self.textBrowser.append(out)
def on_readyReadStandardError(self):
err = self.process.readAllStandardError().data().decode().strip()
self.textBrowser.append(err)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
run.py 看起来像这样(QProcess 的外部 python 程序)
import time
for i in range(5):
print(i)
time.sleep(1)
自己复制试试
我找到了正确的答案
sys.stdout.flush()
所以:
import time
for i in range(5):
print(i)
sys.stdout.flush()
time.sleep(1)