После прочтения литературы по QProcesses и модуля многопроцессорности для python, я все еще испытываю трудности с созданием рабочего и гибкого графического интерфейса, когда в фоновом режиме происходят большие процессы. До сих пор я придумал эту упрощенную версию моего приложения, которая по-прежнему показывает похожие проблемы, о чем многие говорили.многопроцессорная обработка и обновление графического интерфейса - Qprocess или многопроцессорная обработка?
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_())
Это должно быть полностью выполнено, если у вас есть зависимости. На данный момент у меня есть QT-версия моей программы, которая работает с сигналами и слотами; Прежде всего, я считаю, что важно иметь возможность использовать все компьютерные процессоры, поскольку большинство пользователей имеют доступ к 8 ядрам. Таким образом, я хотел бы расширить этот подход с использованием сигнала/слота на многопроцессорную версию, используя multiprocessing
или QProcess
es.
У кого-нибудь есть предложения по использованию или отсутствию QProcess
или multiprocessing
? Хотя они и сложны для меня, QProcess кажется, что он имеет меньше форумов людей, использующих pyQt, поэтому я пошел с многопроцессорной обработкой. Будет ли проще работать с QProcess, поскольку у меня уже есть сигналы/слоты, работающие с потоками?
EDIT: Следует ли добавить такой класс, как предлагается?
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)
большое спасибо за помощь, но я не уверен, что вы на самом деле означает. Должен ли я создать класс, который наследует QProcess и порождает поток из него? Я попробовал этот класс в моем отредактированном вопросе. – chase
Я плохо разбираюсь в python, занимаюсь Qt с C++ годами.Но я немного понимаю, чего вы пытаетесь достичь. Насколько я знаю, 1. '' 'QProcess''' позволяет вам запустить другой процесс (скажем, cmd.exe или firefox.exe или что-то еще) внутри вашего приложения, и вы можете управлять (запускать, останавливать, писать, читать) их. 2. Если вы пытаетесь обработать (или сделать что-то) в фоновом режиме, перейдите в QThread или QTimer или QtConcurrent. Все они будут запускать ваш фрагмент кода в отдельном процессе. Таким образом, вы можете сделать одно из следующих действий. –
a. Используйте '' 'QThread'''. Создайте класс, который наследует QThread и перегружает его метод run(). Напишите в нем свои методы complex_processing_on_spectra. Или вы можете использовать объект Spectra внутри этого класса. Излучайте сигнал, когда происходит итерация. Подключите этот сигнал к слоту, который обновит интерфейс. б. Используйте '' 'QTimer'''. Подключить таймер '' 'timeout()' '' signal с '' 'update_GUI()' '' с интервалом n milisec. c. Используйте '' '' QtConcurrent'''. Но на этот раз вы можете избежать этого. Я не уверен, что это надежный API. –