Как уже сказал, subprocess.call
будет ждать, пока команда завершена.
Но, учитывая, что вы используете PyQt, лучше использовать QProcess, так как это позволит вам использовать сигналы и события, чтобы поддерживать графический интерфейс.
Есть несколько вопросов, о которых стоит подумать.
Во-первых, команда ffmpeg
будет висеть, если выходной файл уже существует, потому что по умолчанию он будет запрашивать у пользователя разрешение на перезапись. Поэтому было бы неплохо добавить флаг -y
или -n
, чтобы справиться с этим.
Во-вторых, команда может также зависать по какой-то неожиданной причине. Поэтому вы должны, вероятно, дать пользователю возможность принудительно убить процесс.
И наконец, что должно произойти, если пользователь попытается закрыть приложение до завершения команды? Вероятно, вам нужно будет обработать closeEvent главного окна, чтобы справиться с этим.
Демонстрационная ниже сценарий показывает некоторые возможные способы обработки вышеуказанных вопросов:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.label = QtGui.QLabel('Elapsed: 0', self)
layout.addWidget(self.label)
self.buttonStart = QtGui.QPushButton('Start', self)
self.buttonStart.clicked.connect(self.handleButtonStart)
layout.addWidget(self.buttonStart)
self.buttonStop = QtGui.QPushButton('Stop', self)
self.buttonStop.setDisabled(True)
self.buttonStop.clicked.connect(self.handleButtonStop)
layout.addWidget(self.buttonStop)
self._process = QtCore.QProcess(self)
self._process.started.connect(self.handleStarted)
self._process.finished.connect(self.handleFinished)
self._process.error.connect(self.handleError)
self._time = QtCore.QTime()
self._timer = QtCore.QTimer(self)
self._timer.timeout.connect(self.handleTimeout)
def closeEvent(self, event):
if self._timer.isActive():
event.ignore()
else:
QtGui.QWidget.closeEvent(self, event)
def handleButtonStart(self):
self._running = True
self._process.start('ffmpeg', [
'-f', 'concat', '-i', 'input.txt',
'-c', 'copy', '-y', 'output.mp4',
], QtCore.QIODevice.ReadOnly)
def handleTimeout(self):
self.label.setText(
'Elapsed: %.*f' % (2, self._time.elapsed()/1000.0))
def handleButtonStop(self):
if self._timer.isActive():
self._process.close()
def handleStarted(self):
self.buttonStart.setDisabled(True)
self.buttonStop.setDisabled(False)
self._time.start()
self._timer.start(50)
def handleFinished(self):
self._timer.stop()
self.buttonStart.setDisabled(False)
self.buttonStop.setDisabled(True)
def handleError(self, error):
if error == QtCore.QProcess.CrashExit:
print('Process killed')
else:
print(self._process.errorString())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 200, 100)
window.show()
sys.exit(app.exec_())
Как @falsetu сказал использовать POPEN вы можете увидеть пример [здесь] (http://stackoverflow.com/a/20451375/1982962) –
@ Kobi K, что мне делать, если я хочу знать, когда процесс будет завершен? – iMath
'Popen.communicate()' wait's для завершения процесса, когда это будет сделано, следующая строка будет предварительно сформирована 'stdOutValue, stdErrValue = communicationRes', и тем самым вы получите stdout и ошибку. –