Python标准模块实现非阻塞键盘输入遇阻,咨询多进程解决方案
用multiprocessing实现独立键盘输入检测的方案
可行性说明
完全可以通过multiprocessing实现独立于动画主进程的键盘输入检测。核心思路是将键盘输入逻辑放到单独的子进程中运行,通过进程间通信(IPC)将按键信息传递给主进程,这样主进程的嵌套动画循环不会阻塞输入检测,也无需依赖需要root权限或阻塞脚本的第三方库。
具体实现步骤
1. 核心原理
- 子进程:专门负责监听键盘输入,使用
tty/termios设置终端为非阻塞模式,持续检测按键并将结果通过multiprocessing.Queue发送给主进程。 - 主进程:运行嵌套双循环的ASCII动画,定期从队列中读取按键信息,根据输入执行相应操作(比如退出动画)。
2. 完整代码示例
import sys import time import multiprocessing import tty import termios import select def keyboard_listener(queue, stop_event): # 保存终端原始设置,退出时恢复 fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: # 设置终端为原始模式,支持非阻塞输入 tty.setraw(sys.stdin.fileno()) while not stop_event.is_set(): # 使用select检测是否有输入,超时0.1秒避免占用过多资源 if select.select([sys.stdin], [], [], 0.1)[0]: key = sys.stdin.read(1) queue.put(key) # 按q直接触发停止 if key.lower() == 'q': stop_event.set() break finally: # 恢复终端设置,防止终端异常 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) def main_animation(): # 初始化进程通信队列和停止事件 input_queue = multiprocessing.Queue() stop_event = multiprocessing.Event() # 启动键盘监听子进程 listener_process = multiprocessing.Process(target=keyboard_listener, args=(input_queue, stop_event)) listener_process.start() try: # 模拟嵌套双循环的ASCII动画 frame_count = 0 while not stop_event.is_set(): # 外层循环:控制动画场景 for scene in ['Scene 1', 'Scene 2']: if stop_event.is_set(): break # 内层循环:逐帧播放场景内容 for frame in [f"{scene} Frame {i}" for i in range(5)]: if stop_event.is_set(): break # 清屏(简单实现,不同终端可能需要调整) sys.stdout.write('\033[H\033[J') sys.stdout.write(f"ASCII Animation:\n{frame}\nPress 'q' to quit\n") sys.stdout.flush() time.sleep(0.2) # 检查队列是否有输入 while not input_queue.empty(): key = input_queue.get() print(f"\nReceived key: {repr(key)}") if key.lower() == 'q': stop_event.set() break frame_count += 1 finally: # 确保子进程终止 stop_event.set() listener_process.join() print("\nAnimation stopped.") if __name__ == "__main__": main_animation()
3. 关键细节说明
- 终端模式恢复:子进程中必须在
finally块恢复终端原始设置,否则程序退出后终端可能无法正常输入(比如无法换行)。 - 进程间通信:使用
multiprocessing.Queue安全传递按键信息,避免共享内存的同步问题。 - 非阻塞检测优化:子进程中用
select加超时的方式检测输入,既不会阻塞子进程,也不会占用过多CPU资源。 - 停止信号同步:通过
multiprocessing.Event实现主进程和子进程的退出同步,确保动画和输入监听都能及时终止。
运行效果
运行脚本后,ASCII动画会在嵌套循环中持续播放,同时子进程独立监听键盘输入。按下任意键都会被捕获,按q键会立即终止动画和程序,不会出现输入无法被捕获的情况。
内容的提问来源于stack exchange,提问作者Muddyblack k
相关产品推荐
相关产品推荐

