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

pynput监听器on_press被自身模拟按键触发的循环问题

解决pynput键盘监听器被自身模拟按键触发的无限循环问题

问题分析

你遇到的核心问题是:pynput的keyboard.Listener会捕获所有按键事件,包括通过Controller模拟的按键。之前用普通布尔变量加延迟的方法失效,是因为多线程环境下普通变量存在可见性问题,且time.sleep()在监听器线程执行时,模拟的按键事件已被捕获,等sleep结束重置变量时,循环已经触发。

解决方案:使用线程安全的标志过滤事件

用threading.Event作为线程安全的控制标志,确保模拟按键期间,监听器回调直接跳过处理逻辑,避免捕获自身触发的事件。

修改后的代码

from pynput import keyboard
from pynput.keyboard import Key, Controller
import threading

k = Controller()
# 线程安全的事件,初始状态为允许处理事件
allow_process = threading.Event()
allow_process.set()

def on_press(key):
    # 若当前不允许处理,直接返回
    if not allow_process.is_set():
        return
    print(key)
    # 禁止处理后续事件
    allow_process.clear()
    try:
        # 执行模拟按键操作
        k.press(key)
    finally:
        # 模拟完成后恢复事件处理
        allow_process.set()

def on_release(key):
    if not allow_process.is_set():
        return
    print(key)
    allow_process.clear()
    try:
        k.release(key)
    finally:
        allow_process.set()

with keyboard.Listener(suppress=True, on_press=on_press, on_release=on_release) as listener:
    listener.join()

替代方案:临时停止/重启监听器

如果不需要保留模拟期间的用户输入,也可以在模拟按键时临时停止监听器,完成后再重启:

from pynput import keyboard
from pynput.keyboard import Key, Controller

k = Controller()

def on_press(key):
    print(key)
    # 停止监听器,避免捕获模拟事件
    listener.stop()
    try:
        k.press(key)
    finally:
        # 重启监听器
        listener.start()

def on_release(key):
    print(key)
    listener.stop()
    try:
        k.release(key)
    finally:
        listener.start()

# 先初始化监听器并启动
listener = keyboard.Listener(suppress=True, on_press=on_press, on_release=on_release)
listener.start()
listener.join()

关键说明

  • threading.Event的set()/clear()操作是原子性的,不会出现多线程下的竞态条件,确保状态同步。
  • suppress=True仅阻止系统接收按键事件(比如不会输入到文本框),但监听器仍然会捕获所有事件(包括模拟的),所以必须在回调中做过滤。
  • 避免在监听器回调中使用time.sleep(),这会阻塞监听器线程,导致事件处理延迟甚至逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:01:04