2016-12-31 11 views
0

アラーム(ファイルbeep.wav)をループしてアラートを表示しようとしています。クラス属性が正しく割り当てられていません

アラートが閉じられると、にすぐにアラームを停止します。

アラームの再生を制御するスレッドを使用するソリューションを試しています。

しかし、それはエラーがスローされます。

Traceback (most recent call last): 
    File "test.py", line 28, in <module> 
    thread.stop() 
    File "test.py", line 21, in stop 
    self.process.kill() 
AttributeError: 'AlarmThread' object has no attribute 'process' 

このエラーがスローになるだろう、なぜ私は本当に知りませんが、しかしself.processAlarmThread.stopが呼び出されたときに、何らかの理由で、割り当てられていない、であるように見えます。

thread.stopのみthread.start後に呼ばれるように私のコードから、それが見えますので、これは、私には意味がありません:

import subprocess 
import threading 

class AlarmThread(threading.Thread): 
    def __init__(self, file_name="beep.wav"): 
     super(AlarmThread, self).__init__() 
     self.file_name = file_name 
     self.ongoing = None 

    def run(self): 
     self.ongoing = True 
     while self.ongoing: 
      self.process = subprocess.Popen(["afplay", self.file_name]) 
      self.process.wait() 

    def stop(self): 
     if self.ongoing is not None: 
      self.ongoing = False 
      self.process.kill() 

thread = AlarmThread() 
thread.start() 
# show_alert is synchronous, an alert must be closed before the script continues 
show_alert("1 second timer") 

thread.stop() 
thread.join() 

答えて

1

あなたは競合状態を持っています。スレッドには起動する準備ができていないので、self.processthread.stop()と呼ぶまでに割り当ててください。あなたは__init__self.processを初期化し、プロセスが本当にそこ

import subprocess 
import threading 

class AlarmThread(threading.Thread): 
    def __init__(self, file_name="beep.wav"): 
     super(AlarmThread, self).__init__() 
     self.lock = threading.Lock() 
     self.file_name = file_name 
     self.ongoing = False 
     self.process = None 

    def run(self): 
     self.ongoing = True 
     while True: 
      with self.lock: 
       if not self.ongoing: 
        break 
       self.process = subprocess.Popen(["afplayer", self.file_name]) 
      self.process.wait() 

    def stop(self): 
     with self.lock: 
      if self.ongoing: 
       self.ongoing = False 
       if self.process: 
        self.process.kill() 


thread = AlarmThread() 
thread.start() 
# show_alert is synchronous, an alert must be closed before the script continues 
show_alert("1 second timer") 

thread.stop() 
thread.join() 
+0

べき'もしself.process'が' self.processではない間: 'であれば、スレッドは終了するまで待つでしょうか? – theonlygusti

+0

このソリューションはまだ動作しません。 – theonlygusti

+0

@theonlygusti - 穴を塞ぐためにロックをいくつか追加しました。私が書いたいくつかのハッキングされたテストでうまくいった。あなたの環境でテストできますか? – tdelaney

0

はい、それは競合状態によって引き起こされたかどうかを確認するためにそれを使用することができます。

The thread hasn't had time to start, create the process and assign self.process by the time you call thread.stop()

しかし、私は単にthread.processが割り当てられていたまで待っ依拠修正が見つかりました:

thread = AlarmThread() 
thread.start() 
while not thread.process: 
    time.sleep(0.1) 

show_alert(message) 

thread.stop() 
thread.join() 
thread.processを確保するために若干変更

私のクラスが常に割り当てられます。

class AlarmThread(threading.Thread): 
    def __init__(self, file_name="beep.wav"): 
     super(AlarmThread, self).__init__() 
     self.file_name = file_name 
     self.ongoing = None 
     self.process = None 

    def run(self): 
     self.ongoing = True 
     while self.ongoing: 
      self.process = subprocess.Popen(["afplay", self.file_name]) 
      self.process.wait() 
      self.process = None 

    def stop(self): 
     if self.ongoing is not None: 
      self.ongoing = False 
      self.process.kill() 
+0

'run'を見ると、' self.ongoing'が設定されているときと 'self.process'が実際に割り当てられているときの間にウィンドウがあります(実行すると" afplay "にかなりの時間がかかります)。そのギャップは 'self.process = None'のために各ループに存在します。また、 'self.ongoing'はTrue/Falseのみでなければなりません...' False'に設定し、 'None'をチェックしてください。 – tdelaney

関連する問題