Python 使用PyQt5运行命令并获取stdout和stderr

Python 使用PyQt5运行命令并获取stdout和stderr,python,pyqt,pyqt5,qprocess,Python,Pyqt,Pyqt5,Qprocess,我想用PyQt5运行命令。我想以时间顺序实时获取标准输出和标准输出 "Output 1" Waiting for 0 seconds, press a key to continue ... "Error 1" Waiting for 0 seconds, press a key to continue ... "Output 2" Waiting for 0 seconds, press a key to continue ... "Error 2" 我分为UI类和Worker类。有几

我想用PyQt5运行命令。我想以时间顺序实时获取标准输出和标准输出

"Output 1"

Waiting for 0 seconds, press a key to continue ...
"Error 1"

Waiting for 0 seconds, press a key to continue ...
"Output 2"

Waiting for 0 seconds, press a key to continue ...
"Error 2"
我分为UI类和Worker类。有几个UI类,但为了简单起见,我只指定了一个

我试图解决这个问题,但我做不到。我无法连接辅助线程和记录器函数

测试ui.py

导入系统 导入子流程 从PyQt5.QtWidgets导入QApplication、QWidget、QHBoxLayout、QVBoxLayout 从PyQt5.QtWidgets导入QPushButton,QTextEdit 从工人进口工人 类TestUI(QWidget): 定义初始化(自): super()。\uuuu init\uuuuu() self.worker=worker() self.btn1=QPushButton(“Button1”) self.btn2=QPushButton(“Button2”) self.btn3=QPushButton(“Button3”) self.result=QTextEdit() self.init_ui() def初始用户界面(自身): self.btn1.点击.连接(self.press_btn1) self.btn2.单击.connect(self.press_btn2) self.btn3.单击.连接(self.press\u btn3) hlayout1=QHBoxLayout() hlayout1.addWidget(self.btn1) hlayout1.addWidget(self.btn2) hlayout1.addWidget(self.btn3) hlayout2=QHBoxLayout() hlayout2.addWidget(self.result) vlayout=QVBoxLayout() vlayout.addLayout(hlayout1) vlayout.addLayout(hlayout2) self.setLayout(vlayout) self.show() def压力btn1(自身): command1=“dir” 路径=“../” self.worker.run_命令(command1,path) self.worker.outSignal.connect(self.logging) def压力btn2(自身): command2=“cd” 路径=“../” self.worker.run_命令(command2,path) self.worker.outSignal.connect(self.logging) def压力btn3(自身): command3=“whoami” 路径=“../” self.worker.run_命令(command3,path) self.worker.outSignal.connect(self.logging) def日志记录(self,str): self.result.append(str.strip()) 如果名称=“\uuuuu main\uuuuuuuu”: APP=QApplication(sys.argv) ex=TestUI() sys.exit(APP.exec_()) worker.py


从PyQt5.QtCore导入QProcess,pyqtSignal
班主任:
外部信号=pyqtSignal(str)
errSignal=pyqtSignal(str)
定义初始化(自):
self.proc=QProcess()
def run_命令(self、cmd、path):
self.proc.setWorkingDirectory(路径)
self.proc.setProcessChannelMode(QProcess.MergedChannels)
self.proc.readyReadStandardOutput.connect(self.onReadyStandardOutput)
self.proc.finished.connect(self.proc.deleteLater)
self.proc.start(cmd)
def onReadyStandardOutput(自):
结果=self.proc.readAllStandardOutput().data().decode()
self.outSignal.emit(结果)
def OnReadyStandarderError(自身):
结果=self.proc.readAllStandardError().data().decode()
self.errSignal.emit(结果)
更新:

应用并进行以下修改仍会使代码失败:

@pyqtlot()
def压力btn1(自身):
command1=“dir”
路径=“../”
self.worker.run_命令(command1,path)
@pyqtSlot()
def压力btn2(自身):
command2=“cd”
路径=“../”
self.worker.run_命令(command2,path)
@pyqtSlot()
def压力btn3(自身):
command3=“test.bat”
路径=“../”
self.worker.run_命令(command3,path)
@pyqtSlot(str)
def日志记录(self,msg):
msg=msg.strip()
如果是味精!="":
self.result.append(msg)
测试.bat

@echo off

echo "Output 1"
timeout /t 1
1>&2 echo "Error 1"
timeout /t 1
echo "Output 2"
timeout /t 1
1>&2 echo "Error 2"

批处理文件问题 这是通过命令提示符运行它时的结果

它每秒实时输出一行

"Output 1"

Waiting for 0 seconds, press a key to continue ...
"Error 1"

Waiting for 0 seconds, press a key to continue ...
"Output 2"

Waiting for 0 seconds, press a key to continue ...
"Error 2"
这是应用程序的结果

3秒后输出整行。时间顺序不对

"Output 1"

Waiting for 1 seconds, press a key to continue ...0

Waiting for 1 seconds, press a key to continue ...0
"Output 2"

Waiting for 1 seconds, press a key to continue ...0
"Error 1"
"Error 2"

我不完全确定,但您可以尝试让Worker从QObject或QWidget继承。我相当肯定,这是用户创建的类发出信号工作所必需的

您有以下错误:

  • 这些信号只在QoObject中工作,因此Worker必须从QoObject继承

  • 建议QProcess不要成为该类的成员,因为我们说任务1正在执行,在未完成的情况下,您尝试执行任务2,以便任务1将被替换,这不是您想要的,相反,QProcess可以作为Worker的子进程来完成,这样您的生命周期就不局限于创建它的方法

  • 如果要分别监视stderr和stdio输出,则不应将processChannelMode与QProcess::MergedChannels连接,因为这将连接两个输出。另一方面,如果消除了上述情况,则必须使用readyreadstandardror信号来了解何时修改stderr

  • 由于QProcess不是该类的成员,因此很难在onReadyStandardOutput和onReadyStandardError中获取QProcess,但为此,必须使用具有发出信号的对象的sender()方法

  • 信号和插槽之间的连接只能进行一次,在您的情况下,您可以按一下btn1、btn2和btn3进行连接,这样您将获得3倍相同的信息

  • 不要使用
    str
    ,因为它是一个内置函数

考虑到上述情况,解决方案是:

worker.py

从PyQt5.QtCore导入QObject、QProcess、pyqtSignal、pyqtSlot
班级工作人员(QObject):
外部信号=pyqtSignal(str)
errSignal=pyqtSignal(str)
def run_命令(self、cmd、path):
proc=QProcess(自)
进程setWorkingDirectory(路径)
proc.readyReadStandardOutput.connect(self.onReadyStandardOutput)
进程readyReadStandardError.connect(self.onReadyStandarderError)
proc.finished.connect(proc.deleteLater)
程序启动(cmd)
@pyqtSlot()
def onReadyStandardOutput(自):
过程=