PyQt4 QProcess状态始终为0,各种插槽也不起作用

时间:2015-07-16 13:06:56

标签: python qt pyqt pyqt4 qprocess

我试图找出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;按钮)以及一个布尔标志,但缺少状态变化的问题仍然存在。

谢谢!

1 个答案:

答案 0 :(得分:1)

startDetached功能是静态。分离的进程由Qt在内部启动,因此永远不会有QProcess对应它。这就是为什么信号不起作用的原因。在您的示例脚本中,myProcess完全是多余的。

根据定义,分离的进程与启动它的进程没有直接的通信方式。你得到的只是一个pid,就是这样。在某些平台上,可以使用该pid来终止进程 - 例如,请参阅os.kill

出于与上述相同的原因,无法重新附加到现有流程。你所拥有的就是那个pid,如果你想在以后重新使用它,它需要以某种方式存储在外部(例如在文件中)。

从广义上讲,您正在处理的问题是Inter-process communication(IPC)。有许多不同的解决方案,因此在决定哪一个最合适之前,您需要更清楚地了解应用程序的结构。