Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
pexpect运行长bash命令挂起wxpythongui_Python_Bash_User Interface_Wxpython_Pexpect - Fatal编程技术网

pexpect运行长bash命令挂起wxpythongui

pexpect运行长bash命令挂起wxpythongui,python,bash,user-interface,wxpython,pexpect,Python,Bash,User Interface,Wxpython,Pexpect,我正在编程一个GUI软件,它有一个终端窗口(wxCtrl),在执行时实时显示外部程序的输出 我尝试了subprocess.Popen,但它没有按预期工作,因为它会在运行时挂起我的GUI,并且只在执行完成后才提供输出 def miExecuteCmd(self, cmd): self.terminal.addText("\n###\n\n") self.terminal.addText("Executing: %s\n" % cmd) args = shlex.split(

我正在编程一个GUI软件,它有一个终端窗口(wxCtrl),在执行时实时显示外部程序的输出

我尝试了subprocess.Popen,但它没有按预期工作,因为它会在运行时挂起我的GUI,并且只在执行完成后才提供输出

def miExecuteCmd(self, cmd):
    self.terminal.addText("\n###\n\n")
    self.terminal.addText("Executing: %s\n" % cmd)
    args = shlex.split(cmd)
    p = subprocess.Popen(args, stdout = subprocess.PIPE)
    output = p.stdout.readlines()
    output = "".join(output)
    self.terminal.addText(output)
    if (p.returncode != None and p.returncode != 0 ):
        self.terminal.addText("Command Execution Problem, return code is %d\n" % p.returncode)
    return output 
现在我试着用pexpect,我读了这篇文章

所以我写了这样的代码

def miExecuteCmd(self, cmd):
    self.terminal.addText("\n###\n\n")
    self.terminal.addText("Executing: %s\n" % cmd)
    output = []
    child = pexpect.spawn(cmd)
    while True:
        try:
            child.expect('\n')
            line = child.before
            output.append(line)
            self.terminal.addText(line)
        except pexpect.EOF:
            break 
    if child.exitstatus != None and child.exitstatus != 0:
        line = "Command Execution Problem, return code is %d\n" % child.exitstatus
        self.terminal.addText(line)
        output.append(line)

    output = "".join(output)

    return output
但当我长时间运行cmd时,GUI仍然会冻结

因此,我要求提供一个简单的pexpect解决方案,允许我操作GUI,同时查看cmd的输出


我阅读了pexpect文档,似乎pexpect.spawn()应该为命令启动一个单独的线程,现在我不知道是否将pexpect.spawn()放在一个新线程中。

无论使用哪种方法执行脚本,GUI窗口都将冻结。您需要将这些命令作为单独的线程执行,以便GUI不会被阻塞。如果您提供了一个代码的最小示例,这会有所帮助,但无论如何,请尝试以下方法:

import thread

def miExecuteCmd(self, cmd):
    #bunch of codes...

def on_execute(self, cmd):
    thread.start_new_thread(self.miExecutecmd, ())

绑定事件处理程序以调用self.on_execute,它将在一个新线程中执行命令

最后,我为我的问题找到了一个很好的解决方案,GUI冻结和wxPython中的线程通信

应该读过这篇文章,它是线程wx.CallAfter()和PubSub的组合,用于解决线程通信问题。因此,在我的例子中,只需添加pexpect来指示要传达的内容

下面是我的run()示例。您需要在上面的链接中查看示例

def run(self):
        wx.CallAfter(self.sendToMainThread, "\n###\n\n")
        text = "Executing: %s\n" % (self.cmd)
        wx.CallAfter(self.sendToMainThread, text)

        child = pexpect.spawn(self.cmd) 
        while True:
            try:
                if self.stopFlag:
                    line = "Stop Buttont Clicked, Stopping External Command... \n"
                    wx.CallAfter(self.sendToMainThread, line)
                    child.terminate(True)
                    child.close()
                    break
                child.expect('\n')
                line = child.before
                wx.CallAfter(self.sendToMainThread, line)
            except pexpect.EOF:
                child.close()
                break
        if child.exitstatus != None and child.exitstatus != 0:
            line = "Command Execution Problem, return code is %d\n" % child.exitstatus
            wx.CallAfter(self.sendToMainThread, line)
        #it looks like next line never happens because of the exception handling above.
        #child.close() make sure child return a code.
        elif child.exitstatus == None:
            line = "Command Execution was interrupted.\n"
            wx.CallAfter(self.sendToMainThread, line)

        #sending an end signal to main thread. command is finished.
        wx.CallAfter(Publisher().sendMessage, "endthread", True)

谢谢你的代码,但这还不完整,我需要新的线程发送信息到主线程来回。我在wxpython中使用PubSub解决了这个问题,很快就会更新。如果你之前提到过,我也可以向你展示!