Win11下GitBash/CMD中Python游戏脚本无法接收键盘输入求助
修复Win11终端下无法接收键盘输入的问题
问题根源
你的脚本使用pynput库监听键盘事件,但在Win11的CMD/GitBash环境中,pynput的全局监听机制容易被Retro游戏窗口抢占焦点,且终端环境的权限限制也会导致事件捕获失败。以下是几种可行的修复方案:
方案一:快速临时修复(无需改代码)
- 以管理员身份运行终端:右键点击CMD或GitBash,选择「以管理员身份运行」,全局键盘监听需要系统权限。
- 手动切换焦点:启动脚本后,先点击终端窗口获取焦点,再按下快捷键(Retro游戏窗口启动后会自动抢焦点,需要手动切回终端)。
方案二:替换为终端友好的键盘库(推荐)
将pynput替换为更适配终端环境的keyboard库,该库专门针对终端输入优化:
- 安装依赖:
pip install keyboard
- 修改代码中的键盘监听逻辑,替换原有的
pynput相关代码:
# 替换原来的from pynput import keyboard为: import keyboard # 在run()方法中,替换原来的on_press、on_release和listener部分: def run(self): print("🕹️ KUNG FU MASTER TRAINER CONTROLS:") print("↑ ↓ ← → : Move/Jump/Duck") print("A: Punch | S: Kick") print("R: Start/Stop recording") print("O: Save state | P: Load state") print("M: Toggle AI control") print("Q: Quit") # 按键按下回调 def on_key_press(e): key = e.name.lower() if key == 'r': self.stop_recording() if self.recording else self.start_recording() elif key == 'o': self.save_game_state() elif key == 'p': self.load_game_state() elif key == 'm': self.toggle_ai() elif key == 'q': # 退出程序 keyboard.unhook_all() self.env.close() exit() elif key == 'a': self.controls['a'] = True elif key == 's': self.controls['s'] = True elif key == 'up': self.controls['up'] = True elif key == 'down': self.controls['down'] = True elif key == 'left': self.controls['left'] = True elif key == 'right': self.controls['right'] = True # 按键释放回调 def on_key_release(e): key = e.name.lower() if key == 'a': self.controls['a'] = False elif key == 's': self.controls['s'] = False elif key == 'up': self.controls['up'] = False elif key == 'down': self.controls['down'] = False elif key == 'left': self.controls['left'] = False elif key == 'right': self.controls['right'] = False # 注册全局钩子 keyboard.on_press(on_key_press) keyboard.on_release(on_key_release) self.env.reset() try: while True: # 原有逻辑保持不变 if self.ai_playing and self.model: frame = self._process_frame(self.env.get_screen()) action, _ = self.model.predict(frame) else: action = [ int(self.controls['up']), int(self.controls['down']), int(self.controls['left']), int(self.controls['right']), int(self.controls['a']), int(self.controls['s']) ] obs, _, done, _ = self.env.step(action) if self.recording: self.current_segment.append((self._process_frame(obs), action)) self.env.render() time.sleep(0.02) if done: self.env.reset() finally: keyboard.unhook_all() self.env.close()
方案三:优化pynput监听逻辑
如果坚持使用pynput,可以调整监听线程的优先级,并强制终端窗口保持焦点:
- 安装额外依赖:
pip install pywin32
- 修改run方法中的监听启动代码:
# 在run()方法中,启动listener后添加强制焦点代码: listener = keyboard.Listener(on_press=on_press, on_release=on_release) listener.start() # 强制终端窗口获取焦点 import win32gui import win32con win32gui.SetForegroundWindow(win32gui.GetConsoleWindow()) # 原有主循环保持不变
内容的提问来源于stack exchange,提问作者kenpeter




