PyQt4 QProcess.startDetached() - can't get return value and PID of spawned process

ぐ巨炮叔叔 提交于 2020-02-25 08:20:36

问题


This is a follow-up question to a previous one (again posted by me): PyQt4 QProcess state always 0, various slots not working too

The code (modified):

Main application: 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()

For now all the Start button does is start the detached process. The idea is for it to be toggable and stop/start the detached process whenever the users interacts with it based on the PID.

The application used for the created process: testCommand.py

#!/usr/bin/env python

while True:
    print "a"

After doing some reading and googling I found out that the startDetached() function returns 2 values in Python (in the C++ it's a boolean function, but it also sets the value of one of its arguments - the pointer pid):

  • bool: tells us if the starting of the detached process was successful or not
  • int: gives the PID of the started process if the operation was successful

Here are the sources I have used for this information:

  • http://doc.qt.io/qt-4.8/qprocess.html#startDetached
  • http://pyqt.sourceforge.net/Docs/PyQt4/qprocess.html (due to current failure to load sourceforge properly here is the cached version: 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)

For some reason this is not working at all. Here are the two situations that I have tested:

  • Trying to get both the bool and int values from the function:

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

    I get this error:

    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
    

    This tells me that I can't iterate over the return value of startDetached() hence only a SINGLE value is actually returned and not two as I have also seen in multiple pieces of code again part of the PyQt4 documentation...

  • Checking what startDetached() actually returns: it seems it only returns an int, which I presume is the PID. However if it's the PID it is not the correct value (looking at the output of htop):

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

I have learned that startDetached() is a static function hence any future interaction with the created process can be done via it's pid but things like calling its state (QProcess.state()) etc. are not possible since there is no object to interact with. The way this (broken) thing works right now is indeed start a detached process but since I don't have any PID that identifies it, the only way of interaction I have is finding manually the PID of the testCommand.py and then executing the appropriate signal via kill.

Does anyone know what I'm doing wrong here? I can go to the basics and start using C/C++ with the various system calls but I would really like to actually learn how to do this with PyQt4 and Python.

Thanks!

EDIT

It seems that startDetached() indeed returns True|False. The PID however is nowhere to be found...Not what one reads in the official documentation.


回答1:


The function startDetached is overloaded in C++, it has several signatures. Depending on the arguments provided, it does not necesseraly return the same thing.

Even if overloading does not exist in Python, you have something similar:

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))


来源:https://stackoverflow.com/questions/31519215/pyqt4-qprocess-startdetached-cant-get-return-value-and-pid-of-spawned-proce

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!