2017-09-19 9 views
-2

PythonとPyQtを学びたいと思っていますが、大部分はうまくいっていますが、PyQtスレッディングに関する大きな問題があります。私はこの問題をPythonの "スレッド"モジュールを使ってうまく動作させるようにしましたが、ときにはSeg Faultエラー(追加情報なし)が発生します。PyQtワーカーにArgを渡すスレッド開始時のスレッド

私はPyQtを正しくスレッドする方法を学びたいと思っています。私は「間違っている」、「間違ったことはしていませんでした」、Maya Poschの投稿、Pyrtt4のPyrt4、Pyqt5のドキュメンテーション、およびチュートリアルやたくさんの例を読んでいます。それ(Stack-Oからのロットを含む)と私はますます混乱してきました。

私はワーカーを起動してその作業を行い、データを返すことができました。私は問題なくexit、emitなどをすることができますが、私は労働者に何らかの引数を渡すことはできません。私はかなりインテリジェントな男ですが、これは私を完全なばかのように感じさせます!私が何か新しいことを読んでそれを試す度に、丸い穴に四角いペグを入れようとしているような気がします。

"moveToThread"機能を使用していますが、私が読んだほとんどの記事によれば、スレッドをサブクラス化するのではなく、正しい方法です(ほとんどの例でサブクラス化されています)。

私は口笛のように聞こえるわけではありませんが、これで私を助けることができれば、私は「あなたがたまらなくするときに送る」以上のものを必要とします。 。私は誰かがこの質問に近づくのを見ましたが、彼らは信じられないほどあいまいでした。そしてStack-Oは、私が他の人の投稿にコメントしたり質問したりするために22の評判ポイントを必要とします...〜sigh

私は大きなスクリプトを模倣するスタブスクリプトを持っています。ここではスタブから関連するコードは次のとおりです。

def pre_Flight_Check(): 
    #count = 0 # I want to pass THIS to the Worker at Worker's start 
    fire_Up_Thread(count) 
#===================== 
def butStop_click(): 
    # Stop Loop/Thread: 
    flagQuit = flagQuit + 1 
#===================== 
# Worker: 
class Worker(QObject): 
    finished = pyqtSignal() 
    intCount = pyqtSignal(int) 

    @pyqtSlot() 
    def looper(self): 
     flagQuit = 0 
     count = 0 # I'd like to pass this into the Worker, not define it here 
     while (count < 5): 
      self.intCount.emit(count) 
      time.sleep(1) 
      count = count + 1 
      if flagQuit != 0: 
       break   
     self.finished.emit() 
#======================== 
objWorker = Worker() 
thrWorker = QThread() 
#======================== 
# Threading stuffs: 
def fire_Up_Thread(count): 
    # NOTE: I CAN pass the "count" var into here, just not to the Worker 
    objWorker.moveToThread(thrWorker) 
    thrWorker.started.connect(objWorker.looper) 
    objWorker.intCount.connect(updateTextBox) 
    objWorker.finished.connect(thrWorker.quit) 
    objWorker.finished.connect(work_finished)   
    # Start the thread: 
    thrWorker.start() 

はFYI:これは、Pythonのスレッドを使用して実装したものです - それは非常にシンプルでストレートフォワードです:

# Loop 
def looper(count): 
    flagQuit = 0 

    while (count < 5): 
     print(count) 
     txtBox1.setText(str(count)) 
     time.sleep(1) 
     count = count + 1 
     # User clicked "Stop" button 
     if flagQuit != 0: 
      break 
    work_finished() 
#======================== 
def pre_Flight_Check(): 
    # Var(s) to send to thread: 
    count = 0 
    # Start Loop/Thread 
    loopTest = threading.Thread(target=looper, args=(count,)) 
    loopTest.setDaemon(True) 
    loopTest.start() 

答えて

-1

変数は、次に作業者に上に引数を渡すために使用することができ、呼び出し可能なように見えることを可能にします。ここでは、元の行です:

thrWorker.started.connect(objWorker.looper) 

と変更されたライン:変更を組み込むために全体のスタブ書き換え用

thrWorker.started.connect(partial(objWorker.looper,count,strIs)) 

そして今:

def pre_Flight_Check(): 
    count = 0 
    strIs = "is: " # NOTE: this is only here to show that more than 1 variable can be included 
    fire_Up_Thread(count,strIs) # 2 vars to pass 
#===================== 
def butStop_click(): 
    flagQuit = flagQuit + 1 
#===================== 
# Worker: 
class Worker(QObject): 
    finished = pyqtSignal() 
    intCount = pyqtSignal(int) 

    @pyqtSlot() 
    def looper(self,count,strIs): # Both vars - "count" and "strIs" 
     flagQuit = 0 
     while (count < 5): 
      strCount = "The count " + strIs + str(count) 
      self.intCount.emit(count) 
      time.sleep(1) 
      count = count + 1 
      # User clicked "Stop" button 
      if flagQuit != 0: 
       break 
     self.finished.emit() 
#======================== 
objWorker = Worker() 
thrWorker = QThread() 
#======================== 
# Threading stuffs: 
def fire_Up_Thread(count,strIs): # Passed in from "pre_Flight_Check" 
    from functools import partial 
    objWorker.moveToThread(thrWorker) 
    thrWorker.started.connect(partial(objWorker.looper,count,strIs)) # All vars are appended to connected target 
    objWorker.intCount.connect(updateTextBox) 
    objWorker.finished.connect(thrWorker.quit) 
    objWorker.finished.connect(work_finished) 
    # Start the thread: 
    thrWorker.start() 

これは動作しますが、それはスレッドですそれは処理が簡単でコストがかかりません。

0

あなたがWorkerを初期化するときだけ引数を渡します「functools」モジュールからの「部分」を使用

class Worker(QObject): 
    finished = pyqtSignal() 
    intCount = pyqtSignal(int) 

    def __init__(self, count): 
     super(Worker, self).__init__() 
     self.count = count 

    @pyqtSlot() 
    def looper(self): 
     flagQuit = 0 
     while (self.count < 5): 
      self.intCount.emit(self.count) 
      time.sleep(1) 
      self.count = self.count + 1 
      if flagQuit != 0: 
       break   
     self.finished.emit() 


count = 0 
objWorker = Worker(count) 
+0

あなたの例では、 "self.count = 0"を指定して、looper(self)の下でWorkerクラスの中で "count"を定義する必要があります。私のすべての引数はその前に定義されているので、単にそれらをWorkerに渡すだけです。私は労働者に私のargsを定義するときに私自身の問題はなかった。 argsはスレッドのものに向かいつつあり、それを超えていません。要約すると、私はpre_Flight_Check関数から、またはThreadのものからWorkerへ、すでに定義されたargsを渡すことができる必要があります。 – user7207540

+0

申し訳ありませんが、あなたのサンプルをコピーして貼り付けるときに間違ってそこに残しました。私は私の答えを更新しました – user3419537

+0

このような迅速な応答ありがとう!私は今、次のエラーが発生しています: "objWorker = Worker(count)"の前に "count"を定義しないと、 "count 'が定義されていません。 "RuntimeError:スーパークラス__init __()型のWorkerが呼び出されていない"という前に定義しています。 – user7207540

関連する問題