我正在尝试循环警报(在文件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.process
由于某种原因,在调用AlarmThread.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()
答案 0 :(得分:1)
你有竞争条件。线程没有时间开始,创建流程并在您致电self.process
时指定thread.stop()
。您可以在self.process
中初始化__init__
并使用它来查看流程是否真的存在
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()
答案 1 :(得分:0)
是的,这是由竞争条件引起的。
线程没有时间开始,创建流程并在您拨打
self.process
时分配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()