PyQt4 QProcess.startDetached() - 无法获取生成进程的返回值和 PID

rba*_*dar 1 python qt qprocess pyqt4

这是上一个问题的后续问题(我再次发布):PyQt4 QProcess 状态始终为 0,各种插槽也不起作用

代码(修改):

主要应用:qprocess_test.py

#!/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.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):
        res, pid = QProcess.startDetached(self.command, self.args)
            print "Starting process\n", str(res), " | pid = ", str(pid)

    def toggleButton(self, value):
        if value == True:
            print "Lalalala!"
        else:
            print "Didadida!"

def main(): 
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

现在开始按钮所做的就是启动分离的进程。这个想法是它是可切换的,并在用户基于 PID 与其交互时停止/启动分离的进程。

用于创建进程的应用程序:testCommand.py

#!/usr/bin/env python

while True:
    print "a"
Run Code Online (Sandbox Code Playgroud)

在做了一些阅读和谷歌搜索之后,我发现 startDetached() 函数在 Python 中返回 2 个值(在 C++ 中它是一个布尔函数,但它也设置了它的一个参数的值 - 指针pid):

  • bool:告诉我们分离进程的启动是否成功
  • int:如果操作成功,则给出启动进程的PID

以下是我用于此信息的来源:

由于某种原因,这根本不起作用。以下是我测试过的两种情况:

  • 试图从函数中获取 bool 和 int 值:

    res, pid = self.myProcess.startDetached(self.command, self.args)
    
    Run Code Online (Sandbox Code Playgroud)

    我收到此错误:

    Traceback (most recent call last):
      File "./qprocess_test.py", line 48, in toggleProcess
        res, pid = self.myProcess.startDetached(self.command, self.args)
    TypeError: 'bool' object is not iterable
    
    Run Code Online (Sandbox Code Playgroud)

    这告诉我,我无法迭代startDetached()的返回值,因此实际上只返回了一个 SINGLE 值,而不是两个,正如我在 PyQt4 文档的多段代码中再次看到的那样......

  • 检查startDetached()实际返回的内容:它似乎只返回一个 int,我认为它是 PID。但是,如果是 PID,则它不是正确的值(查看htop的输出):

    val = QProcess.startDetached(self.command, self.args)
    # val = 0 (always!)
    
    Run Code Online (Sandbox Code Playgroud)

我了解到startDetached()是一个静态函数,因此任何未来与创建的进程的交互都可以通过它的 pid 来完成,但是像调用它的状态 (QProcess.state()) 之类的事情是不可能的,因为没有对象可以交互和。这个(损坏的)事情现在的工作方式确实是启动一个分离的进程,但由于我没有任何识别它的 PID,我唯一的交互方式是手动查找testCommand.py的 PID,然后执行通过kill发出适当的信号。

有谁知道我在这里做错了什么?我可以从基础开始使用 C/C++ 和各种系统调用,但我真的很想真正学习如何使用 PyQt4 和 Python 来做到这一点。

谢谢!

编辑

似乎 startDetached() 确实返回 True|False。然而,PID 无处可寻……不是在官方文档中读到的。

Mel*_*Mel 6

该函数startDetached在 C++ 中被重载,它有几个签名。根据提供的参数,它不一定返回相同的内容。

即使Python 中不存在重载,您也有类似的东西:

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QProcess

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    command = "./testCommand.py"
    args = [""]

    #"regular" startDetached : give two arguments, get a boolean
    process=QProcess()
    re=process.startDetached("ls",["."])
    print(re)
    print(type(re))

    #"overload" startDetached : give three arguments, get a tuple(boolean,PID)
    process2=QProcess()
    re,pid=process2.startDetached("ls",["."],".")
    print(re,pid)
    print(type(re),type(pid))
Run Code Online (Sandbox Code Playgroud)