在研究了如何正确地要求线程停止之后,我陷入了意想不到的行为。
我正在开展一个个人项目。我的目标是在 RaspberryPi 上运行一个专用于家庭自动化的程序。
我的代码结构如下:
- 第一个线程专用于调度:每天的同一时间,我在 GPIO 输出上发送信号
- 第二个线程专门用于监视键盘的手动事件
- 每当按下特定键时,我想启动一个新线程,专门用于另一个例程,就像我的第一个线程一样
这是我的操作方法:
import schedule
from pynput import keyboard
import threading
first_thread = threading.Thread(target=heating, name="heating")
second_thread = threading.Thread(target=keyboard, name="keyboard")
first_thread.start()
second_thread.start()
stop_event = threading.Event()
我的加热程序定义为:
def heating():
def job():
GPIO.output(4,GPIO.HIGH)
return
schedule.every().day.at("01:00").do(job)
while True:
schedule.run_pending()
time.sleep(0.5)
我的键盘监视器定义如下:
def keyboard():
def on_press(key):
if key == keyboard.Key.f4:
shutter_thread = threading.Thread(name="shutter", target=shutter, args=(stop_event,))
shutter_thread.start()
if key == keyboard.Key.f5:
stop_event.set()
with keyboard.Listener(on_press=on_press,on_release=on_release) as listener:
listener.join()
我的shutter
线程目标与加热线程目标类似:
def shutter(stop_event):
def open():
GPIO.output(6,GPIO.HIGH)
return
t = threading.currentThread()
schedule.every().day.at("22:00").do(open)
while not stop_event.is_set():
schedule.run_pending()
time.sleep(0.5)
问题是每次我按下按键启动我的 shutter
线程时,都会调用快门例程,但是:
- 我的
shutter
例程中的job
执行了两次 - 第一个线程中的
作业
现在每次按计划执行两次! - 一旦我按下按键要求
快门
线程停止,加热
(第一个)线程就会恢复到其原始(且正确)的行为,但是shutter
线程不停止
我不知道为什么启动这个新线程会对另一个线程的行为产生这样的修改。为什么我的停止事件不起作用?
我做错了什么?
最佳答案
由于您使用 schedule
框架来管理任务,一个干净的解决方案是使用同一框架的 API 来取消作业(而不是使用 threading.Event
)。这样,任务管理就保留在计划
内,而用户交互则由线程
处理。
def keyboard():
tasks = []
def on_press(key):
if key == keyboard.Key.f4:
# Shutter task.
tasks.append(
schedule.every().day.at("22:00").do(lambda: GPIO.output(6,GPIO.HIGH))
)
if key == keyboard.Key.f5:
schedule.cancel_job(tasks.pop(-1))
with keyboard.Listener(on_press=on_press,on_release=on_release) as listener:
listener.join()
# Heating task.
schedule.every().day.at("01:00").do(lambda: GPIO.output(4,GPIO.HIGH))
# Start keyboard listener.
ui = threading.Thread(target=keyboard)
ui.start()
while True:
schedule.run_pending()
time.sleep(0.5)
关于Python 从另一个线程启动/停止线程会导致意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51565356/