2017-01-27 9 views
2

私は比較的新しいPythonですが、大量のデータを処理するためにはかなり便利なプログラムを手に入れることができました。別のPythonスクリプトを使って順次プログラムを呼び出すことができますが、GUIを作成してマルチスレッドを使用して、プログラミングの面倒をすべて知らなくても他の人が使用できるようにしたかったのです。私はGUIをうまく作成し、信号とスロットを使って双方向にデータを送ることができます。私が問題を抱えているのは、同じ機能を持つ複数のスレッドを作成することです。Python3を使ってpyqt5でQthreadsを正しくロックする方法

私はいくつかの研究を行っており、関数はスレッドセーフである必要があり、残念なことに私は、スレッドセーフではないscipyからcurve_fit()を使用しているためではありません。だから、このフォーラムや他の記事で読んだ内容に基づいて、私はmutex.lock()を使うべきですが、curve_fit()を呼び出すときに "SystemError:null引数を内部ルーチンに渡します"

ここにいくつかのサンプルがありますコードは、私がやっていることを証明するために:、私が正常に一つだけのスレッドを呼び出すコードを実行することができます

class ZthObject(QtCore.QObject): 
    killthread = False 
    finished = QtCore.pyqtSignal() 
    textBox = QtCore.pyqtSignal(str) 
    def __init__(self, wetFilePath, dryFilePath, outFilePath, side, parent=None): 
     super(self.__class__, self).__init__() 
     self.wetFilePath = wetFilePath 
     self.dryFilePath = dryFilePath 
     self.outFilePath = outFilePath 
     self.side = side 
     self.mutex = QtCore.QMutex() 
    def cleanup(self): 
     ZthObject.killthread = True 

# def ZthCalculation(self, wetFilePath, dryFilePath, outFilePath, side): 
    def ZthCalculation(self): 
     #calculations here 
. 
. 
. 
     print("waypoint2") 
     self.mutex.lock() 
     popt, pcov = curve_fit(Foster6, timeShort, ZthjcShort, p0 = [Rs, taus]) 
     self.mutex.unlock() 
. 
. 
. 
     self.finished.emit() 

import sip 
    sip.setapi('QString', 2) 

    import sys, time 
    from PyQt5 import QtCore, QtGui, uic, QtWidgets 
    from ZthCalculation import ZthObject 

    qtCreatorFile = "PyQtZthUI_01.ui" # Enter file here. 

    Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile) 

    #class MyApp(QtGui.QMainWindow, Ui_MainWindow): 
    class MyApp(QtWidgets.QMainWindow, Ui_MainWindow): 
     def __init__(self): 
      super(self.__class__, self).__init__() 
      QtWidgets.QMainWindow.__init__(self) 
      Ui_MainWindow.__init__(self) 
      self.setupUi(self) 
      self.RunButton.clicked.connect(self.RunZthTest) 
    . 
    . 
    . 
     def RunZthTest(self): 
    #create as processes instead of threads??? 
    #   self.Process1 = QtCore.QProcess() 
      self.Thread1 = QtCore.QThread() 
      self.obj1 = ZthObject(self.InputWet1.text(), self.InputDry1.text(), self.Output1.text(), self.side1) 
      self.obj1.moveToThread(self.Thread1) 
      self.Thread1.started.connect(self.obj1.ZthCalculation) 
      self.obj1.textBox.connect(self.updateTextBox1) 
      self.signal1 = self.obj1.finished.connect(self.Thread1.quit) 
      self.Thread1.setObjectName("Thread1") 
      self.Thread1.start() 
      time.sleep(.1) 

      self.Thread2 = QtCore.QThread() 
      self.obj2 = ZthObject(self.InputWet2.text(), self.InputDry2.text(), self.Output2.text(), self.side2) 
      self.obj2.moveToThread(self.Thread2) 
      self.Thread2.started.connect(self.obj2.ZthCalculation) 
      self.obj2.textBox.connect(self.updateTextBox2) 
      self.signal2 = self.obj2.finished.connect(self.Thread2.quit) 
      self.Thread2.setObjectName("Thread2") 
      self.Thread2.start() 
      time.sleep(.1) 

      self.Thread3 = QtCore.QThread() 
      self.obj3 = ZthObject(self.InputWet3.text(), self.InputDry3.text(), self.Output3.text(), self.side3) 
      self.obj3.moveToThread(self.Thread3) 
      self.Thread3.started.connect(self.obj3.ZthCalculation) 
      self.obj3.textBox.connect(self.updateTextBox3) 
      self.signal3 = self.obj3.finished.connect(self.Thread3.quit) 
      self.Thread3.setObjectName("Thread3") 
      self.Thread3.start() 
    . 
    . 
    . 

    if __name__ == "__main__": 
     app = QtWidgets.QApplication(sys.argv) 
     window = MyApp() 
     window.show() 
    # sys.exit(app.exec_()) 
     app.exec_() 

を別のファイルでは、私がスレッドとして呼び出しています主な機能を持っていますしかし、複数のスレッドを呼び出すと、出力ウィンドウはea用に 'waypoint2'を出力しますchのスレッドが呼び出され、上記のシステムエラーでクラッシュします。

私は間違っていますか? Qthreadsではなく別のプロセスを使用する必要がありますか?スレッドの仕組みを誤解していますか?私は彼らに独立した変数空間での操作を望みます。

答えて

2

mutexを使用すると、実際に関数の内部を共有する他のすべてがmutexを尊重している場合に、スレッドセーフなものになります。この場合、mutexを使用している間にcurve_fitへの同時呼び出しが妨げられているため、関数についてスレッドが安全でないことがわからないため、他の何かが別のスレッド(例えば、メインスレッド)でコードのスレッド安全でないビットを同時に使用してください。

Python GILが本当のスレッディングを妨げるという事実(スレッドがCPUバインドではなくIOバインドであれば、スレッド化はPythonでスピードを向上させるだけです)と組み合わせて、マルチプロセスモデルに移行することをお勧めします。

関連する問題