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

Posted

技术标签:

【中文标题】PyQt4 QProcess.startDetached() - 无法获得衍生进程的返回值和 PID【英文标题】:PyQt4 QProcess.startDetached() - can't get return value and PID of spawned process 【发布时间】:2015-07-20 14:32:28 【问题描述】:

这是上一个问题的后续问题(再次由我发布):PyQt4 QProcess state always 0, various slots not working too

代码(修改):

主应用: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()

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

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

#!/usr/bin/env python

while True:
    print "a"

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

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

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

http://doc.qt.io/qt-4.8/qprocess.html#startDetached http://pyqt.sourceforge.net/Docs/PyQt4/qprocess.html(由于当前未能正确加载 sourceforge,这里是缓存版本:http://webcache.googleusercontent.com/search?q=cache:lQ-ixJIbVQQJ:pyqt.sourceforge.net/Docs/PyQt4/qprocess.html+&cd=1&hl=en&ct=clnk&gl=de&client=ubuntu)

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

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

res, pid = self.myProcess.startDetached(self.command, self.args)

我收到此错误:

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

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

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

val = QProcess.startDetached(self.command, self.args)
# val = 0 (always!)

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

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

谢谢!

编辑

看来 startDetached() 确实返回 True|False。然而,PID 却无处可寻...不是官方文档中所读到的。

【问题讨论】:

对于第二种情况:我认为 startDetached() 返回的 int 是布尔值,而不是 PID (0=False, 1=True) 根据 PyQt Doc,返回 PID 的实际函数是(bool, int pid) QProcess.startDetached (QString program, QStringList arguments, QString workingDirectory)。注意第三个参数。 Qt 文档还指出,如果未给出 workingDirectory,则启动的进程会从生成进程中获取值。顺便说一句,我也尝试从这个函数中获取一个元组(通过添加圆括号)——同样的错误是 bool 是不可迭代的。 @tmoreau 我不这么认为,因为 1)当 Python 对 bool 类型的值使用 False|True 时为什么要返回 0|1(这将是一个糟糕的移植机制,可能导致很多混乱)和 2)在这种情况下为 False 将意味着该进程未启动(至少阅读文档是这样说的),但该进程已启动并正常运行。 只有一种方法可以确定:做print(type(val))。我有bool,但 val print "True",所以我们可能缺少一些东西。我在 Python3.4 和 PyQt 4.11 【参考方案1】:

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

即使overloading does not exist in 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))

【讨论】:

再次感谢!顺便说一句,由于 startDetached() 的性质,您不需要过程变量。它工作得很好。此外,我真的必须从头到尾开始阅读文档——PyQt4 文档明确描述了 QProcess.startDetached() 的所有 3 个版本以及它们返回的内容...... -_-

以上是关于PyQt4 QProcess.startDetached() - 无法获得衍生进程的返回值和 PID的主要内容,如果未能解决你的问题,请参考以下文章

如何让 PyQt4 与 PyCharm 一起工作

导入 PyQt4 模块

python 安装PyQt4

PyQT4 库的问题

PyQt4 - 拖放

运行 PyQt4 演示 --- 如何?