Multiprocessing und GUI-Aktualisierung – Qprocess oder Multiprocessing?

Nachdem ich die Literatur über QProcesses und das Multiprocessing-Modul für Python gelesen habe, habe ich immer noch Schwierigkeiten, eine funktionierende und reaktionsfähige GUI zu erstellen, während große Prozesse im Hintergrund laufen. Bisher habe ich diese vereinfachte Version meiner Anwendung gefunden, die immer noch ähnliche Probleme zeigt, was viele beschrieben haben.

from PyQt4 import QtCore, QtGui import multiprocessing as mp import numpy as np import sys class Spectra: def __init__(self, spectra_name, X, Y): self.spectra_name = spectra_name self.X = X self.Y = Y self.iteration = 0 def complex_processing_on_spectra(self, pipe_conn): self.iteration += 1 pipe_conn.send(self.iteration) class Spectra_Tab(QtGui.QTabWidget): def __init__(self, parent, spectra): self.parent = parent self.spectra = spectra QtGui.QTabWidget.__init__(self, parent) self.treeWidget = QtGui.QTreeWidget(self) self.properties = QtGui.QTreeWidgetItem(self.treeWidget, ["Properties"]) self.step = QtGui.QTreeWidgetItem(self.properties, ["Iteration #"]) self.consumer, self.producer = mp.Pipe() # Make process associated with tab self.process = mp.Process(target=self.spectra.complex_processing_on_spectra, args=(self.producer,)) def update_GUI(self, iteration): self.step.setText(1, str(iteration)) def start_computation(self): self.process.start() while(True): message = self.consumer.recv() if message == 'done': break self.update_GUI(message) self.process.join() return class MainWindow(QtGui.QMainWindow): def __init__(self, parent = None): QtGui.QMainWindow.__init__(self) self.setTabShape(QtGui.QTabWidget.Rounded) self.centralwidget = QtGui.QWidget(self) self.top_level_layout = QtGui.QGridLayout(self.centralwidget) self.tabWidget = QtGui.QTabWidget(self.centralwidget) self.top_level_layout.addWidget(self.tabWidget, 1, 0, 25, 25) process_button = QtGui.QPushButton("Process") self.top_level_layout.addWidget(process_button, 0, 1) QtCore.QObject.connect(process_button, QtCore.SIGNAL("clicked()"), self.process) self.setCentralWidget(self.centralwidget) self.centralwidget.setLayout(self.top_level_layout) # Open several files in loop from button - simplifed to one here X = np.arange(0.1200,.2) Y = np.arange(0.1200,.2) self.spectra = Spectra('name', X, Y) self.spectra_tab = Spectra_Tab(self.tabWidget, self.spectra) self.tabWidget.addTab(self.spectra_tab, 'name') def process(self): self.spectra_tab.start_computation() return if __name__ == "__main__": app = QtGui.QApplication([]) win = MainWindow() win.show() sys.exit(app.exec_()) 

Dies sollte voll ausführen können, wenn Sie die Abhängigkeiten haben. Im Moment habe ich eine QThreaded Version von meinem Programm, das mit Signalen und Slots arbeitet; Hweever, ich denke, es ist wichtig, die Möglichkeit zu haben, alle Computer-Prozessoren zu verwenden, da die meisten Benutzer ~ 8 Kerne zur Verfügung haben. Also, ich möchte diese Signal / Slot-Thread-Ansatz auf die Multiprocessed-Version mit multiprocessing oder QProcess es erweitern.
Hat jemand Vorschläge für die Verwendung von QProcess oder multiprocessing ? Während sie beide kompliziert zu mir sind, scheint QProcess, als ob es weniger Foren von Menschen mit pyQt hat, also ging ich mit Multiprocessing. Wäre es einfacher, mit QProcess zu gehen, da ich schon Signale / Slots mit Threads habe?

EDIT: Soll ich eine Klasse wie folgt hinzufügen?

 class My_Process(QtCore.QProcess): def __init__(self, spectra): QtCore.QProcess.__init__(self) self.spectra = spectra def worker(self): QtConcurrent.run(self.spectra, self.spectra.complex_processing_on_spectra) def run(self): QtCore.QObject.connect(self, QtCore.SIGNAL(QTimer.timeout()), self.worker) 

  • Wie gehst du pyqt .ui Code in Python?
  • Warum ist PyQt connect () Syntax so ausführlich?
  • PyQt Tableview Hintergrundfarbe basierend auf Textwert statt True oder False
  • Einfachste Weg für PyQT Threading
  • Hast du ein py-poppler-qt Beispiel?
  • So löschen Sie QTreeWidgetItem
  • QTableview spezifizieren Standard Suchfeld
  • Gib ein Objekt in einer Rolle in Python zurück und bekomme eine Referenz eines anderen Objekts in QML
  • 2 Solutions collect form web for “Multiprocessing und GUI-Aktualisierung – Qprocess oder Multiprocessing?”

    QProcess ist zum Lesen und Schreiben an Pipes (Shell / cmd). Verwenden Sie eine davon.

    1. Erstellen Sie eine Klasse mit Worker-Funktion und führen Sie sie als Thread von QtConcurrent.run(object, method, args)
    2. Verbinden Sie QTimer.timeout() mit Ihrer Worker-Funktion.

    Obwohl die Frage alt ist und beantwortet wurde, möchte ich noch etwas klären:

    • QtConcurrent ist in PyQt nicht verfügbar.
    • Threads in Qt mit C ++ unterscheiden sich von PyQt oder Python Threads. Letztere müssen Pythons GIL (Global Interpreter Lock) erwerben, wenn sie laufen, was effektiv bedeutet, dass es keine wirkliche Parallelität zwischen python / pyqt Threads gibt.

    Python-Threads sind in Ordnung, um die Gui reagieren, aber Sie werden keine Performance-Verbesserungen für CPU-gebundene Aufgaben sehen. Ich empfehle die Verwendung von multiprocessing zusammen mit einem QThread auf Ihrem Hauptprozess, der die Kommunikation mit dem Kind-Prozess behandelt. Sie können Signale und Slots zwischen Ihrem Haupt (Gui) und Ihrem Kommunikations-Thread verwenden.

    Bildbeschreibung hier eingeben

    Edit: Ich hatte gerade das gleiche Problem und tat etwas in dieser Richtung:

     from multiprocessing import Process, Queue from PyQt4 import QtCore from MyJob import job_function # Runner lives on the runner thread class Runner(QtCore.QObject): """ Runs a job in a separate process and forwards messages from the job to the main thread through a pyqtSignal. """ msg_from_job = QtCore.pyqtSignal(object) def __init__(self, start_signal): """ :param start_signal: the pyqtSignal that starts the job """ super(Runner, self).__init__() self.job_input = None start_signal.connect(self._run) def _run(self): queue = Queue() p = Process(target=job_function, args=(queue, self.job_input)) p.start() while True: msg = queue.get() self.msg_from_job.emit(msg) if msg == 'done': break # Things below live on the main thread def run_job(input): """ Call this to start a new job """ runner.job_input = input runner_thread.start() def handle_msg(msg): print(msg) if msg == 'done': runner_thread.quit() runner_thread.wait() # Setup the OQ listener thread and move the OQ runner object to it runner_thread = QtCore.QThread() runner = Runner(start_signal=runner_thread.started) runner.msg_from_job.connect(handle_msg) runner.moveToThread(runner_thread) 
    Python ist die beste Programmiersprache der Welt.