Python pynput按键记录回放出现多余重复按键输出问题
问题描述
开发支持按键记录与回放的程序时,触发回放后会出现额外字符输出的异常:测试时手动输入hello后调用playStrokes()执行回放,实际输出内容为helloello,预期仅输出hello。此前曾在playStrokes()的循环中打印变量i排查逻辑问题,未发现循环计数存在异常。
对应实现代码如下:
from pynput import keyboard from pynput.keyboard import Key, Controller keys = Controller() def playStrokes(): for i in range(len(strokes)): keys.tap(strokes[i]) strokes = [] def on_press(key): if key == keyboard.Key.shift: print(strokes) playStrokes() return False try: strokes.append(key) except AttributeError: print("ERROR") with keyboard.Listener( on_press=on_press) as keyListener: keyListener.join()
问题原因
异常由两个逻辑问题共同导致:
- 监听器停止顺序错误:pynput 键盘监听器只有在
on_press回调返回False后才会终止监听。原有代码检测到作为触发键的shift时,会先执行完整的回放逻辑,等回放全部结束后才返回False关闭监听器,回放过程中模拟的按键事件会被正常运行的监听器捕获,存在事件干扰风险。 - 触发键状态冲突:按下shift触发回放时,shift键处于物理按下的状态,此时立刻执行回放,第一个模拟按键
h会与按下的shift形成组合键,不会被识别为普通文本字符输入;后续模拟按键触发时shift已被松开,正常输出ello,和之前手动输入的hello拼接后就得到了异常结果helloello。
修复方案
调整回放执行时机,消除按键状态冲突和监听器干扰:
- 检测到shift触发键后立刻返回
False,先终止键盘监听器,避免模拟按键被监听捕获 - 增加100ms左右的短延时,等待物理按下的shift键完全释放,消除组合键冲突
- 等监听器完全退出、触发键状态复位后,再执行回放逻辑
修复后的可运行代码:
from pynput import keyboard from pynput.keyboard import Key, Controller import time keys = Controller() def playStrokes(): # 等待触发键shift完全释放,避免组合键冲突 time.sleep(0.1) for i in range(len(strokes)): keys.tap(strokes[i]) strokes = [] def on_press(key): if key == keyboard.Key.shift: print(strokes) # 先返回False停止监听器 return False try: strokes.append(key) except AttributeError: print("ERROR") # 启动监听器,阻塞到监听器完全退出 with keyboard.Listener(on_press=on_press) as keyListener: keyListener.join() # 监听器关闭、按键状态复位后再执行回放 playStrokes()
补充说明:pynput的键盘监听器默认是全局被动监听,不会拦截物理按键的原始输入,如果你需要记录按键时不向焦点窗口输出原始字符,需要调用平台对应API实现输入拦截,pynput本身不提供该能力。
内容的提问来源于stack exchange,提问作者Aryan Mehra
相关产品推荐
相关产品推荐

