我有一个调用子程序的程序。当子程序使用 Popen 运行时,我需要禁用运行按钮并启用停止按钮。但是,由于Popen打开了一个新进程,因此程序完成后应该打印的内容会立即打印出来。我尝试添加self.p.communicate()
after Popen
,但 GUI 将冻结直到子程序运行完毕,因此停止按钮将不起作用。
这是我的程序:
def gui(QtGui.QWidget):
...
self.runButton = QtGui.QPushButton('Run')
self.stopButton = QtGui.QPushButton('Stop')
self.runButton.clicked.connect(self.run)
self.stopButton.clicked.connect(self.kill)
self.runButton.setEnabled(True)
self.stopButton.setEnabled(False)
def run(self):
self.runButton.setEnabled(False)
self.p = subprocess.Popen(sample.exe)
#self.p.communicate()
self.stopButton.setEnabled(True)
print "Finish running" #without communicate() it will print out before .exe finish running
def kill(self):
self.p.kill()
self.stopButton.setEnabled(False)
print 'You have stop the program'
self.runButton.setEnabled(True)
我正在使用 Window7、Python 2.7、pyqt4。我不必使用子进程,任何打开并能够杀死子程序的东西都可以。
提前致谢。
Edit:尝试使用QProcess
正如达诺建议的那样。我已将以下代码添加到我的程序中:
def gui(QtCore.Widget):
self.process = QtCore.QProcess(self)
def run(self):
self.process.start(exe_path)
self.process.started.connect(self.onstart)
self.process.finished.connect(self.onfinish)
self.runButton.setEnabled(False)
#self.p = subprocess.Popen(sample.exe) #removed
#self.p.communicate() #removed
def onstart (self):
self.stopButton.setEnabled(True)
self.runButton.setEnabled(False)
print "Started\n"
def onfinish (self):
self.stopButton.setEnabled(False)
self.runButton.setEnabled(True)
print "Finish running\n"
def kill(self):
self.process.kill()
#self.p.kill() #removed
这是输出:
点击“运行”(子程序运行结束时输出)
Finish running
第二次点击“运行”
Started
点击“停止”
Finish running
Finish running
第三次单击“运行”
Started
Started
点击“停止”
Finish running
Finish running
Finish running
这里发生了一些事情。
p = subprocess.Popen(exe)
不等待exe
完成——它会尽快返回exe
已开始。
p.communicate()
确实等待子进程结束,因此它会阻塞您的 GUI 线程(GUI 冻结直到子进程退出)。
为了避免阻塞 GUI,您可以检查是否p.poll()
回报None
找出是否p
进程仍在运行。通常 GUI 框架提供了一种设置定期回调的方法(例如,Qt 的 QTimer)——您可以调用p.poll()
那里。
或者放置阻塞调用(例如p.wait()
)进入后台线程并在完成时通知 GUI 线程(发出信号,生成事件)。
质量过程由@dano建议 https://stackoverflow.com/questions/28220197/how-to-do-stuff-during-and-after-a-child-process#comment44804834_28220197已经内置了通知机制(finished
信号)。
As @三菠萝 说 https://stackoverflow.com/questions/28220197/how-to-do-stuff-during-and-after-a-child-process#comment44814595_28220197:如果您不希望多次调用回调,请不要多次连接同一信号。你的情况没有必要打电话.start()
在同一个流程实例上多次:
def run(self):
self.runButton.setEnabled(False) # call it first because
# processes are not started instantly
self.process = QtCore.QProcess(self)
self.process.started.connect(self.onstart) # connect "start" signal
self.process.finished.connect(self.onfinish)
self.process.start(exe_path, args) # then start
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)