I have a program that call to an subprogram. While the subprogram is running with Popen, I need the run button to be disable and the stop button to enable. However, because Pop
p = subprocess.Popen(exe)
does not wait for exe
to finish -- it returns as soon as exe
is started.
p.communicate()
does wait for the child process to end and therefore it blocks your GUI thread (GUI freezes until the subprocess exits).
To avoid blocking the GUI, you could check whether p.poll()
returns None
to find out whether p
process is still running. Usually a GUI framework provides a way to set up periodic callbacks (e.g., QTimer for Qt) -- you can call p.poll()
there.
Or put the blocking call (such as p.wait()
) into a background thread and notify GUI thread on completion (emit signal, generate an event).
QProcess suggested by @dano already has the notification mechanism built-in (finished
signal).
As @three_pineapples said: do not connect the same signal multiple times if you don't want the callbacks to be called multiple times. There is no point in your case to call .start()
on the same process instance more than once:
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