pexpect运行长bash命令挂起wxpythongui
我正在编程一个GUI软件,它有一个终端窗口(wxCtrl),在执行时实时显示外部程序的输出 我尝试了subprocess.Popen,但它没有按预期工作,因为它会在运行时挂起我的GUI,并且只在执行完成后才提供输出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(
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解决了这个问题,很快就会更新。如果你之前提到过,我也可以向你展示!