2017-01-27 5 views
2

나는 비교적 Python에 익숙하지 않지만 많은 양의 데이터를 처리하기 위해 실행하기에 합리적으로 유용한 프로그램을 얻을 수 있었다. 필자는 다른 파이썬 스크립트를 사용하여 순차적으로 프로그램을 호출하는 여러 세트의 데이터를 순차적으로 실행할 수 있지만 GUI를 작성하고 멀티 스레딩을 사용하여 다른 사람들이 프로그래밍의 모든 기능을 알지 못해도 사용할 수있게하려고했습니다. GUI를 성공적으로 만들었고 신호와 슬롯을 사용하여 양방향으로 데이터를 공급할 수있었습니다. 내가 문제를 겪고있는 것은 같은 기능을 가진 다중 쓰레드를 만드는 것이다.Python3을 사용하여 pyqt5에서 Qthreads를 올바르게 잠그는 법

필자는 약간의 연구를했으며 기능이 threadsafe가되어야하며, 불행히도 threadafe가 아닌 scipy에서 curve_fit()을 사용하고 있기 때문에 필자가 아닙니다. 그래서,이 포럼과 다른 사람들이 읽었던 것을 토대로 mutex.lock()을 사용해야 만합니다. 그러나 curve_fit()을 호출 할 때 "SystemError : null argument to internal routine"을 얻었습니다.

다음은 몇 가지 샘플입니다. 코드는 내가 무엇을했는지 보여 : 내가 성공적으로 하나 개의 스레드를 호출하는 코드를 실행할 수 있습니다

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

뮤텍스를 사용하면 함수의 내부를 공유하는 다른 모든 것이 뮤텍스를 존중하는 경우 실제로는 스레드 안전성이 보장됩니다. 이 경우 뮤텍스를 사용하면 동시에 curve_fit을 호출 할 수 없으므로 함수에 대한 스레드가 안전하지 않다는 것을 알지 못하므로 그 밖의 다른 함수가 또 다른 스레드 (예 : 메인 스레드)에서 코드의 스레드 안전하지 않은 비트를 동시에 사용하십시오.

Python GIL이 실제 스레딩을 방해한다는 사실 (스레드가 CPU 바인딩이 아닌 IO 바인딩 인 경우 스레딩은 파이썬에서 속도 향상 만 제공함)과 함께 멀티 프로세스 모델로 이동하는 것이 좋습니다.