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

为何无法第四次按下ESC键?Python鼠标坐标捕获脚本问题排查

问题原因及解决方案

错误原因

代码中键盘监听器的on_press回调函数内使用了阻塞式的raw_input()操作。pynput的键盘监听器运行在独立的后台线程中,每次按下esc后,该线程会被raw_input()阻塞,直至用户输入内容。多次重复此操作后,监听器线程因频繁阻塞出现状态异常,无法再捕获后续的esc按键事件,导致第四次按下esc时无响应。

修改方案

将用户输入逻辑移至主线程,避免阻塞键盘监听器线程。通过线程事件控制鼠标捕获的暂停与恢复,让键盘监听器仅负责触发操作信号,不处理阻塞输入。

修改后的代码

#coding=utf-8
from pynput import keyboard
from pynput import mouse
import threading

running = True
pause_event = threading.Event()
pause_event.set()  # 初始状态允许捕获鼠标坐标

print('The script is capturing the coordinates of the cursor...')

def get_coords(x, y):
    if running and pause_event.is_set():
        print("Now at: {}".format((x, y)))

def on_press(key):
    global user_input_signal
    if key == keyboard.Key.esc:
        pause_event.clear()  # 暂停鼠标捕获
        user_input_signal = True  # 通知主线程处理用户输入

user_input_signal = False

# 启动鼠标监听器
mouse_listener = mouse.Listener(on_move=get_coords)
mouse_listener.start()

# 启动键盘监听器
keyboard_listener = keyboard.Listener(on_press=on_press)
keyboard_listener.start()

try:
    while True:
        if user_input_signal:
            user_input_signal = False
            print('The script has stopped. Do you wish to continue? (y/n)')
            while True:
                answer = raw_input().strip().lower()
                if answer == 'y':
                    pause_event.set()  # 恢复鼠标捕获
                    print('The script was successfully resumed...')
                    break
                elif answer == 'n':
                    running = False
                    print('The script has finished...')
                    # 停止所有监听器
                    mouse_listener.stop()
                    keyboard_listener.stop()
                    break
                else:
                    print('Invalid answer. Please enter "y" to continue or "n" to end the script.')
            if not running:
                break
except KeyboardInterrupt:
    # 捕获Ctrl+C,优雅停止监听器
    mouse_listener.stop()
    keyboard_listener.stop()

# 等待监听器线程结束
mouse_listener.join()
keyboard_listener.join()

修改说明

  • 使用threading.Event()实现鼠标捕获的暂停/恢复控制,避免在回调中阻塞线程。
  • 键盘监听器仅设置标记信号,由主线程处理用户输入,确保监听器线程始终能响应新的键盘事件。
  • 主线程负责处理用户输入逻辑,不会影响监听器的正常运行,支持无限次触发esc按键操作。

内容的提问来源于stack exchange,提问作者Anonibot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:06:01