Python秒表开发问题:按下Esc键无法终止while循环
问题:按下Esc键后秒表循环未停止
我正在尝试用Python开发一款秒表,目前遇到的问题是:当listener返回False时,我的while循环并未停止。
我的代码
from pynput.keyboard import Key, Listener import time def pressOn(key): x = 'Press: {}'.format(key) # 调试用打印 print(x) def pressOff(key): y = 'Release: {}'.format(key) # 调试用打印 print(y) if key == Key.esc: return False t = 0 stop = True with Listener(on_press = pressOn, on_release = pressOff) as listener: while True: print(f'it has been {t} seconds') t += 1 time.sleep(1) if listener == False: break listener.join() print(f'Final time {t} second(s)')
无按键操作时的输出
>>> it has been 0 seconds >>> it has been 1 seconds >>> it has been 2 seconds
按下Esc键后的实际输出
在0秒和1秒消息之间按下并释放1和Esc键,之后按其他键无响应,输出如下:
>>> it has been 0 seconds >>> Press: '1' >>> Release: '1' >>> Press: Key.esc >>> Release: Key.esc >>> it has been 1 seconds >>> it has been 2 seconds >>> it has been 3 seconds >>> it has been 4 seconds >>> it has been 5 seconds
期望输出
>>> it has been 0 seconds >>> Press: '1' >>> Release: '1' >>> Press: Key.esc >>> Release: Key.esc >>> Final time 1 second(s)
解决方案
问题出在两个核心点:
- 错误的停止判断逻辑:
if listener == False:完全无效,listener是Listener对象实例,永远不会等于布尔值False,无法通过该条件触发循环终止。 - 阻塞式sleep导致响应延迟:
time.sleep(1)会让主线程完全阻塞1秒,即使按下Esc,也要等sleep结束才会检查停止条件,导致多执行一次计时循环。
修改后的代码如下:
from pynput.keyboard import Key, Listener import time # 定义共享的运行控制标志 running = True def pressOn(key): print(f'Press: {key}') def pressOff(key): global running print(f'Release: {key}') if key == Key.esc: running = False return False # 停止listener线程 t = 0 with Listener(on_press=pressOn, on_release=pressOff) as listener: while running: print(f'it has been {t} seconds') t += 1 # 拆分长sleep为多次短检查,避免阻塞太久 for _ in range(10): if not running: break time.sleep(0.1) listener.join() print(f'Final time {t} second(s)')
修改说明
- 用全局变量
running作为循环的控制开关,按下Esc时在pressOff中设置running = False,同时返回False停止listener线程。 - 将原来的1秒sleep拆分成10次0.1秒的短sleep,每次sleep后检查
running状态,确保能及时响应停止指令,避免多走一次完整的计时循环。
内容的提问来源于stack exchange,提问作者ShaggyWaaggy
相关产品推荐
相关产品推荐

