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

Python脚本用锁实现异步键盘暂停,长按按键为何永久卡住?

长按按键导致程序永久卡住的原因及解决办法

问题根源

你的代码核心问题在于长按按键时,pynput会重复触发on_press事件,而threading.Lock是不可重入锁——同一个线程如果已经持有锁,再次调用acquire()会直接阻塞线程,最终导致死锁:

  1. 首次按下按键,on_press成功获取锁,主线程因无法拿到锁进入暂停状态;
  2. 长按期间系统重复发送按键按下事件,on_press再次被调用,此时listener线程已持有锁,再次调用acquire()会让listener线程卡住;
  3. 释放按键时,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:45:03