如何不使用KeyboardInterrupt退出提醒程序?keyboard.is_pressed致通知不显示
问题描述
我正在编写一个提醒程序,当时间到达时会向用户发送通知,希望用户可以通过按下一个按键来关闭通知。曾尝试使用KeyboardInterrupt功能,但想要用单个字符而非CTRL+C,因此使用了keyboard.is_pressed函数。
原代码如下:
import time import plyer import keyboard reminder = input("What would you like to set a reminder for? ") while True: mode = str(input("For how long? Type s for seconds, m for minutes, or h for hours: ")) if mode == 's': local_time = float(input("In how many seconds? ")) break elif mode == 'm': local_time = float(input("In how many minutes? ")) local_time *= 60 break elif mode == 'h': local_time = float(input("In how many hours? ")) local_time *= 3600 break else: print("Invalid input, please try again.") time.sleep(local_time) def notfiy(): while True: plyer.notification.notify(title = "Time's Up", message = reminder, timeout = 3) if keyboard.is_pressed("q"): break else: break
原本不使用键盘中断时,由于while True语句,通知会持续弹出,除非重启程序;但使用keyboard.is_pressed函数后,通知不再弹出,寻求解决方法。
问题分析
- notify函数逻辑错误:函数内的
else: break语句导致不管用户是否按下q,循环都会直接终止,通知仅会尝试弹出一次(甚至可能因系统延迟还没显示就退出了)。 - 瞬间检查按键不可靠:
keyboard.is_pressed是瞬间检测按键状态,用户很难在通知弹出的瞬间按下q,需要给足够的等待时间并持续监听。
修复方案
调整notify函数的逻辑,使用循环持续弹出通知,同时在每次通知弹出后等待一段时间并监听按键;也可以改用线程配合keyboard.wait实现更流畅的监听。
基础修复版本
import time import plyer import keyboard reminder = input("What would you like to set a reminder for? ") while True: mode = input("For how long? Type s for seconds, m for minutes, or h for hours: ").strip().lower() if mode == 's': local_time = float(input("In how many seconds? ")) break elif mode == 'm': local_time = float(input("In how many minutes? ")) local_time *= 60 break elif mode == 'h': local_time = float(input("In how many hours? ")) local_time *= 3600 break else: print("Invalid input, please try again.") time.sleep(local_time) def notify(): print("Reminder active! Press 'q' to stop notifications.") while True: # 弹出通知 plyer.notification.notify(title="Time's Up", message=reminder, timeout=3) # 等待3秒(和通知超时一致),期间持续检测q键 start_time = time.time() while time.time() - start_time < 3: if keyboard.is_pressed("q"): print("Notifications stopped.") return time.sleep(0.1) # 降低CPU占用 # 调用通知函数 notify()
关键修改点
- 移除了
else: break语句,让循环可以持续执行 - 在每次通知弹出后,添加3秒的等待窗口,期间持续检测
q键按下状态 - 加入
time.sleep(0.1)减少循环的CPU占用 - 增加控制台提示,告知用户操作方式
更流畅的线程版本
import time import plyer import keyboard import threading reminder = input("What would you like to set a reminder for? ") while True: mode = input("For how long? Type s for seconds, m for minutes, or h for hours: ").strip().lower() if mode == 's': local_time = float(input("In how many seconds? ")) break elif mode == 'm': local_time = float(input("In how many minutes? ")) local_time *= 60 break elif mode == 'h': local_time = float(input("In how many hours? ")) local_time *= 3600 break else: print("Invalid input, please try again.") time.sleep(local_time) def notify(): print("Reminder active! Press 'q' to stop notifications.") stop_event = threading.Event() def wait_for_quit(): keyboard.wait('q') stop_event.set() # 启动后台线程监听按键 threading.Thread(target=wait_for_quit, daemon=True).start() while not stop_event.is_set(): plyer.notification.notify(title="Time's Up", message=reminder, timeout=3) # 等待3秒或直到收到停止信号 stop_event.wait(timeout=3) print("Notifications stopped.") # 调用通知函数 notify()
这个版本用后台线程监听按键,不会阻塞通知循环,用户在任何时候按下q都能立刻停止通知,体验更流畅。
内容的提问来源于stack exchange,提问作者Shania Jones
相关产品推荐
相关产品推荐

