Python QProcess.readAllStandardOutput()不';我好像什么都没读过-PyQt

Python QProcess.readAllStandardOutput()不';我好像什么都没读过-PyQt,python,pyqt,qprocess,Python,Pyqt,Qprocess,以下是代码示例: class RunGui (QtGui.QMainWindow) def __init__(self, parent=None): ... QtCore.Qobject.connect(self.ui.actionNew, QtCore.SIGNAL("triggered()"), self.new_select) ... def normal_output_written(self, qprocess):

以下是代码示例:

class RunGui (QtGui.QMainWindow)

    def __init__(self, parent=None):

        ...
        QtCore.Qobject.connect(self.ui.actionNew, QtCore.SIGNAL("triggered()"), self.new_select)
        ...


    def normal_output_written(self, qprocess):
        self.ui.text_edit.append("caught outputReady signal") #works
        self.ui.text_edit.append(str(qprocess.readAllStandardOutput())) # doesn't work


    def new_select(self):
        ...
        dialog_np = NewProjectDialog()
        dialog_np.exec_()
        if dialog_np.is_OK:
            section = dialog_np.get_section()
            project = dialog_np.get_project()
            ...
            np = NewProject()
            np.outputReady.connect(lambda: self.normal_output_written(np.qprocess))
            np.errorReady.connect(lambda: self.error_output_written(np.qprocess))
            np.inputNeeded.connect(lambda: self.input_from_line_edit(np.qprocess))
            np.params = partial(np.create_new_project, section, project, otherargs)
            np.start()

class NewProject(QtCore.QThread):

    outputReady = QtCore.pyqtSignal(object)
    errorReady = QtCore.pyqtSignal(object)
    inputNeeded = QtCore.pyqtSignal(object)
    params = None
    message = ""

    def __init__(self):
        super(NewProject, self).__init__()
        self.qprocess = QtCore.QProcess()
        self.qprocess.moveToThread(self)
        self._inputQueue = Queue()

    def run(self):
        self.params()

    def create_new_project(self, section, project, otherargs):
        ...
        # PyDev for some reason skips the breakpoints inside the thread
        self.qprocess.start(command)
        self.qprocess.waitForReadyRead()
        self.outputReady.emit(self.qprocess) # works - I'm getting signal in RunGui.normal_output_written()
        print(str(self.qprocess.readAllStandardOutput())) # prints empty line
        .... # other actions inside the method requiring "command" to finish properly.

这个想法被彻底击败了——让GUI运行脚本并与进程通信。这个特定示例中的挑战是,当命令运行应用程序时,在QProcess中启动的脚本需要用户输入(确认)。因此,我必须能够启动脚本,获取所有输出并对其进行分析,等待问题出现在输出中,然后返回答案,让它完成,然后在create_new_project()中继续执行其他操作。

我不知道这是否能解决您的整体问题,但我在这里看到了一些设计问题

  • 您正在线程之间传递qprocess,而不仅仅是发送带有qprocess结果的自定义信号
  • 您使用的类级属性可能应该是实例属性
  • 从技术上讲,您甚至不需要QProcess,因为您正在线程中运行它,并主动使用阻塞调用。它可能很容易成为一个子流程。Popen…但无论如何,我可能会建议进行如下更改:

    class RunGui (QtGui.QMainWindow)
        
        ...
    
        def normal_output_written(self, msg):
            self.ui.text_edit.append(msg) 
    
        def new_select(self):
            ...
                np = NewProject()
                np.outputReady.connect(self.normal_output_written)
                np.params = partial(np.create_new_project, section, project, otherargs)
                np.start()
    
    class NewProject(QtCore.QThread):
    
        outputReady = QtCore.pyqtSignal(object)
        errorReady = QtCore.pyqtSignal(object)
        inputNeeded = QtCore.pyqtSignal(object)
    
        def __init__(self):
            super(NewProject, self).__init__()
    
            self._inputQueue = Queue()
            self.params = None
    
        def run(self):
            self.params()
    
        def create_new_project(self, section, project, otherargs):
            ...
            qprocess = QtCore.QProcess()
            qprocess.start(command)
            if not qprocess.waitForStarted():
                # handle a failed command here
                return
    
            if not qprocess.waitForReadyRead():
                # handle a timeout or error here
                return
    
            msg = str(self.qprocess.readAllStandardOutput())
            self.outputReady.emit(msg) 
    
    不要绕过QProcess。只需发出数据。并从threads方法中创建它,使其自动归该线程所有。您的外部类实际上不应该知道该QProcess对象。它甚至不需要是成员属性,因为它只在操作期间需要

    还要确保正确检查命令是否已成功启动,是否正在运行和输出数据

    更新 为了澄清您可能遇到的一些问题(根据评论),我想建议,如果您需要对需要定期用户输入的流程进行交互控制,那么QProcess可能不是最佳选择。对于运行从开始到结束只生成输出的脚本来说,这应该是可行的,尽管真正使用子流程要容易得多。对于需要用户长期输入的脚本,最好使用。它允许您生成一个流程,然后观察各种模式,您知道这些模式将指示需要输入:

    foo.py

    import time
    
    i = raw_input("Please enter something: ")
    print "Output:", i
    time.sleep(.1)
    print "Another line"
    time.sleep(.1)
    print "Done"
    
    import pexpect
    import time
    
    child = pexpect.spawn("python foo.py")
    child.setecho(False)
    
    ret = -1
    while ret < 0:
        time.sleep(.05)
        ret = child.expect("Please enter something: ")
    
    child.sendline('FOO')
    while True:
        line = child.readline()
        if not line:
            break
        print line.strip()
    
    # Output: FOO
    # Another line
    # Done
    
    test.py

    import time
    
    i = raw_input("Please enter something: ")
    print "Output:", i
    time.sleep(.1)
    print "Another line"
    time.sleep(.1)
    print "Done"
    
    import pexpect
    import time
    
    child = pexpect.spawn("python foo.py")
    child.setecho(False)
    
    ret = -1
    while ret < 0:
        time.sleep(.05)
        ret = child.expect("Please enter something: ")
    
    child.sendline('FOO')
    while True:
        line = child.readline()
        if not line:
            break
        print line.strip()
    
    # Output: FOO
    # Another line
    # Done
    
    import-pexpect
    导入时间
    child=pexpect.spawn(“pythonfoo.py”)
    child.setecho(False)
    ret=-1
    当ret<0时:
    时间。睡眠(.05)
    ret=child.expect(“请输入内容:”)
    child.sendline('FOO')
    尽管如此:
    line=child.readline()
    如果不是直线:
    打破
    打印行.strip()
    #输出:FOO
    #另一行
    #完成
    
    我已经应用了你的建议,但仍然不起作用。我尝试使用QProcess和Popen。当我使用Qprocess时,我会在控制台中看到底层程序的输出,但它不会出现在我的GUI中。我真的开始怀疑python2.6中是否有我目前“被迫”使用的bug。我将实现更改为使用Popen,它适用于我正在启动的所有不需要用户输入的流程,即以某种方式完成的所有流程。但是,当涉及到中间停止的一个工作时,我试图运行的底层程序是运行java应用程序的启动脚本。这可能是问题的原因吗?我敢打赌,您在这里没有遇到任何bug。很可能您只是在代码中遗漏了一些内容,因为我的示例只能显示您在这个特定问题中所要求的内容的一小部分。您可能只需要对整个过程进行代码审查。您可能还需要查看
    pexpect
    模块,以便与需要定期输入的进程进行交互通信。请参阅我的pexpect更新示例。只需尝试将QProcess全部删除,并使用pexpect或subprocess。尽管如此,pexpect应该能够完成您需要的一切。你可能会做一个阻塞
    ,而不管怎样,
    循环,读取行,并用字符串值发出你自己的信号。在正常情况下,pexpect应该做这个把戏,所以我接受答案。