Python脚本用锁实现异步键盘暂停,长按按键为何永久卡住?
长按按键导致程序永久卡住的原因及解决办法
问题根源
你的代码核心问题在于长按按键时,pynput会重复触发on_press事件,而threading.Lock是不可重入锁——同一个线程如果已经持有锁,再次调用acquire()会直接阻塞线程,最终导致死锁:
- 首次按下按键,
on_press成功获取锁,主线程因无法拿到锁进入暂停状态; - 长按期间系统重复发送按键按下事件,
on_press再次被调用,此时listener线程已持有锁,再次调用acquire()会让listener线程卡住; - 释放按键时,listener线程已阻塞,无法执行
on_release里的release(),锁被永久占用,主线程也一直阻塞在acquire(),程序彻底卡住。
解决办法
推荐使用threading.Event实现暂停/恢复逻辑,它更适合这种“开关”式的线程同步场景:
from pynput import keyboard import threading import time # 初始化事件为激活状态(非暂停) pause_event = threading.Event() pause_event.set() def on_press(key): try: # 仅在未暂停时触发暂停操作 if pause_event.is_set(): pause_event.clear() print("Paused") except AttributeError: pass def on_release(key): # 恢复事件,允许主线程继续执行 pause_event.set() print("Unpaused") if key == keyboard.Key.esc: return False listener = keyboard.Listener( on_press=on_press, on_release=on_release) listener.start() while True: time.sleep(0.01) # 事件未激活时阻塞,激活时立即执行后续代码 pause_event.wait() print("Hello")
如果坚持使用锁,可以配合标志位避免重复获取锁:
from pynput import keyboard import threading import time pause_lock = threading.Lock() is_paused = False def on_press(key): global is_paused try: with pause_lock: if not is_paused: is_paused = True print("Paused") except AttributeError: pass def on_release(key): global is_paused with pause_lock: is_paused = False print("Unpaused") if key == keyboard.Key.esc: return False listener = keyboard.Listener( on_press=on_press, on_release=on_release) listener.start() while True: time.sleep(0.01) with pause_lock: if not is_paused: print("Hello")
内容的提问来源于stack exchange,提问作者CalebK
相关产品推荐
相关产品推荐

