Я пытаюсь запустить несколько процессов с очередью и получить результат для всех процессов, используя QProcess
, но у меня есть пара проблем. Я использую QSpinBox
, чтобы настроить максимальное количество процессов для одновременного запуска, и я могу заставить все нормально работать в основном потоке, или если я запускаю цикл с процессами в QObject
, но я не могу заставить его работать правильно в a QThread
.
Я знаю, что нет необходимости использовать потоки с QProcess
, но с циклом у меня почти нет выбора. При запуске в основном потоке он на мгновение зависает до тех пор, пока процессы не запустятся, и я бы предпочел, чтобы он работал более плавно.
Я получаю только ошибки, пытаясь запустить процессы в QThread
, если только я не использую что-то вроде _process.waitForFinished()
, но проблема с этим в том, процессы запускаются только по одному.
Есть ли у кого-нибудь какие-либо предложения, чтобы заставить это работать правильно? В настоящее время я использую Pyside2, но ответ для Pyside2 или PyQt5 будет в порядке. Спасибо.
import queue
import sys
from PySide2.QtCore import QProcess, QTextCodec, QThread, Qt
from PySide2.QtWidgets import QApplication, QWidget, QSpinBox, \
QPushButton, QVBoxLayout
class Window(QWidget):
def __init__(self):
QWidget.__init__(self)
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.queue = queue.Queue()
layout = QVBoxLayout(self)
self.startBtn = QPushButton('Start', clicked=self.addToQueue)
self.spinBox = QSpinBox(value=3)
layout.addWidget(self.spinBox)
layout.addWidget(self.startBtn)
self.taskList = ['my.exe -value','my.exe -value','my.exe -value','my.exe -value',
'my.exe -value','my.exe -value','my.exe -value','my.exe -value']
def addToQueue(self):
for i in self.taskList:
self.queue.put(i)
self.sendToThread()
def sendToThread(self):
vals = {'max': self.spinBox.value()}
self.taskThread = TaskThread(self.queue, vals)
self.taskThread.start()
def closeEvent(self, event):
event.accept()
class TaskThread(QThread):
def __init__(self, queue=None, vals=None, parent=None):
QThread.__init__(self, parent)
self.queue = queue
self.vals = vals
self.maxProcs = self.vals.get('max')
self.procCount = 0
def run(self):
self.start_procs()
def start_procs(self):
while not self.queue.empty() and self.procCount < self.maxProcs:
cmd = self.queue.get()
_process = QProcess(self)
_process.setProcessChannelMode(QProcess.MergedChannels)
self.codec = QTextCodec.codecForLocale()
self._decoder_stdout = self.codec.makeDecoder()
_process.readyReadStandardOutput.connect(lambda process=_process: self._ready_read_standard_output(process))
_process.started.connect(self.procStarted)
_process.finished.connect(self.procFinished)
_process.finished.connect(self.decreaseCount)
_process.finished.connect(self.start_procs)
_process.start(cmd)
self.procCount += 1
def _ready_read_standard_output(self, process):
self.out = process.readAllStandardOutput()
self.text = self._decoder_stdout.toUnicode(self.out)
print(self.text)
def decreaseCount(self):
if self.procCount <= 0:
pass
else:
self.procCount -= 1
def procStarted(self):
print('started')
def procFinished(self):
print('finished')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.resize(200, 100)
window.show()
sys.exit(app.exec_())