You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用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函数后,通知不再弹出,寻求解决方法。

问题分析
  1. notify函数逻辑错误:函数内的else: break语句导致不管用户是否按下q,循环都会直接终止,通知仅会尝试弹出一次(甚至可能因系统延迟还没显示就退出了)。
  2. 瞬间检查按键不可靠: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:47:46