我有一个使用QThreads和Signals / Slots与GUI通信的程序。 它具有如下所示的简化形式。
但是,我想将其更改为QProcess,以便我可以利用多核处理。有一个简单的方法吗?
如果我只是将QThread
更改为QProcess
,则进程没有moveToThread()
函数。我一直在尝试多种不同的多核处理方法,例如Pipes()
模块中的Queues()
和multiprocessing
,但我无法正常工作。所以,我认为使用QProcess
会更容易,因为我已经在Qtland。
以下是我对QThreads
,信号和广告位的简化代码。
from PyQt4 import QtCore, QtGui
import multiprocessing as mp
import numpy as np
import sys
class Spectra(QtCore.QObject):
update_signal = QtCore.pyqtSignal(str)
done_signal = QtCore.pyqtSignal()
def __init__(self, spectra_name, X, Y):
QtCore.QObject.__init__(self)
self.spectra_name = spectra_name
self.X = X
self.Y = Y
self.iteration = 0
@QtCore.pyqtSlot()
def complex_processing_on_spectra(self):
for i in range(0,99999):
self.iteration += 1
self.update_signal.emit(str(self.iteration))
self.done_signal.emit()
class Spectra_Tab(QtGui.QTabWidget):
start_comp = QtCore.pyqtSignal()
kill_thread = QtCore.pyqtSignal()
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 #"])
thread = QtCore.QThread(parent=self)
self.worker = self.spectra
self.worker.moveToThread(thread)
self.worker.update_signal.connect(self.update_GUI)
self.worker.done_signal.connect(self.closeEvent)
self.start_comp.connect(self.worker.complex_processing_on_spectra)
self.kill_thread.connect(thread.quit)
thread.start()
@QtCore.pyqtSlot(str)
def update_GUI(self, iteration):
self.step.setText(0, iteration)
def start_computation(self):
self.start_comp.emit()
def closeEvent(self):
print 'done with processing'
self.kill_thread.emit()
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_())
答案 0 :(得分:2)
进程没有moveToThread()
,因为进程存在于自己的内存空间中,因此无法看到MainWindow
或其中任何成员。您开始使用QProcess
的应用程序应该能够作为独立应用程序执行。
要在另一个QProcess
中运行光谱,您需要将光谱设置为单独的可执行模块,而不是现在的MainWindow成员。
编辑:
您需要定义最不依赖于MainWindow
的自包含模块 - 它只能是光谱过程,或者是带有制表符的光谱过程。您可以在构造或标准输入中传递信息以进行处理,并通过标准输出从流程中检索数据。选择律师进行处理时的关键思想是尽量减少流程与MainWindow之间的沟通和依赖。您可以将过程视为简单的C程序:
int main(int argc,char* argv[]);
你可以在启动时传递参数,必要时通过cin / stdin从MainWindow获取额外的输入,通过cout / stdout / stderr将MainWindow
输出一些结果(QProcess
有接口)。< / p>