我试图找出QProcess( Linux !)的工作方式,因为我将需要它用于我的项目(注意:不使用suprocess或多线程) !该过程也必须与主应用程序分离!)。这是一个用于演示一些基本功能的小代码:
#!/usr/bin/python
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QProcess
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.myProcess = QProcess(self)
self.myProcess.finished.connect(self.onFinished) # NEVER called
self.myProcess.stateChanged.connect(self.onStateChanged) # NEVER called
self.myProcess.started.connect(self.onStarted) # NEVER called
self.command = "./testCommand.py"
self.args = [""]
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
qbtn = QtGui.QPushButton('Start', self)
qbtn.clicked.connect(self.toggleProcess)
qbtn.resize(qbtn.sizeHint())
hbox.addWidget(qbtn)
# This button is for testing the responsiveness of the GUI after the QProcess has been started
qbtn2 = QtGui.QPushButton('Click me', self)
qbtn2.setCheckable(True)
qbtn2.toggled.connect(self.toggleButton)
qbtn2.resize(qbtn2.sizeHint())
hbox.addWidget(qbtn2)
self.setLayout(hbox)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('QProcess controlled by a button')
self.show()
def toggleProcess(self):
# process states (based on Qt docs):
# 0 - not running
# 1 - starting
# 2 - running
# For some reason state is ALWAYS 0
if self.myProcess.state() == 0:
self.myProcess.startDetached(self.command, self.args)
print "Starting process"
print "Process state", str(self.myProcess.state())
elif self.myProcess.state() == 1:
print "Process is starting"
return
else:
print "Stopping process"
self.myProcess.close()
def toggleButton(self, value):
if value == True:
print "Lalalala!"
else:
print "Didadida!"
def onStarted(self):
print "Process started"
def onFinished(self):
print "Process stopped"
def onStateChanged(self):
print "Process has changed state"
def __del__(self):
if self.myProcess.state() == 1 or self.myProcess.state() == 2:
self.myProcess.close()
else:
pass
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
testCommand.py 如下:
版本1:
#!/usr/bin/env python
count = 0
while count < 10:
print "c"
count = count + 1
VERSION 2:在这里,我尝试一个无限的过程来查看GUI是否被阻止。
#!/usr/bin/env python
while True:
print "c"
我在这里遇到了多个问题。首先,QProcess.state()函数总是返回0,因此我永远不会在 toggleProcess()函数中的IF语句的另外两种情况下登陆。因为这个过程没有变化。状态没有信号被发射......永远。无论我选择 testCommand.py 的VERSION 1,它只运行10次循环,还是VERSION 2运行无限运行直到进程关闭,结果始终为状态0,即使我可以看到进程正在运行(在VERSION 2中,您可以获得无限的&#34; c&#34;字符行)。在我使用VERSION 2的情况下,我无法停止进程(因为它的状态没有改变因此从未调用 QProcess.close()所以如果我关闭我的主应用程序,我创建一个必须通过htop或类似进程管理器杀死的孤立进程。我知道 QProcess.startDetached()会创建一个分离的进程,但我仍然希望通过&#34; Start&#34;来控制该进程的执行。按钮。顺便说一句,当我使用 QProcess.execute()时,我会得到相同的行为,这会创建一个子流程并相应地冻结GUI运行所需的时间(在VERSION 2中这是无限期的)。 / p>
谁能告诉我为什么会这样?我想要的只是能够启动一个分离的过程,但仍然能够通过相同的按钮终止它。我也尝试过一个可检查按钮(比如&#34;点击我&#34;按钮)以及一个布尔标志,但缺少状态变化的问题仍然存在。
谢谢!
答案 0 :(得分:1)
startDetached功能是静态。分离的进程由Qt在内部启动,因此永远不会有QProcess
对应它。这就是为什么信号不起作用的原因。在您的示例脚本中,myProcess
完全是多余的。
根据定义,分离的进程与启动它的进程没有直接的通信方式。你得到的只是一个pid,就是这样。在某些平台上,可以使用该pid来终止进程 - 例如,请参阅os.kill。
出于与上述相同的原因,无法重新附加到现有流程。你所拥有的就是那个pid,如果你想在以后重新使用它,它需要以某种方式存储在外部(例如在文件中)。
从广义上讲,您正在处理的问题是Inter-process communication(IPC)。有许多不同的解决方案,因此在决定哪一个最合适之前,您需要更清楚地了解应用程序的结构。