Mac环境Python3 CLI开发:实现实时按键读取与上下箭头切换输入
适配macOS Python3的CLI实时输入方案
以下方案无第三方依赖,完全满足无需回车读按键、上下箭头翻历史的需求。
实现逻辑
- 切换终端默认行缓冲模式为原始字符模式,实现单按键实时读取
- 自动识别特殊按键序列(方向键、退格、回车等),对应执行历史翻页、删除、结束输入逻辑
- 预留历史记录操作接口,可自行修改历史数据来源与读写逻辑
完整可运行代码
import sys import tty import termios # 示例命令历史,可替换为你自己的历史存储逻辑 COMMAND_HISTORY = [ "cd /home/user", "ls -al", "python3 script.py", "git status", "echo hello world" ] def custom_input(prompt: str = "Enter a value here:") -> str: # 保存原始终端属性 fd = sys.stdin.fileno() old_terminal_settings = termios.tcgetattr(fd) current_input = [] # 历史指针,0代表未翻历史,1代表最新一条历史,以此类推 history_pointer = 0 try: # 切换终端为原始字符模式 tty.setraw(sys.stdin.fileno()) # 输出提示语 sys.stdout.write(prompt) sys.stdout.flush() while True: # 读取单个字符 ch = sys.stdin.read(1) # 识别功能键序列(方向键等以ESC开头,共3个字符) if ch == "\x1b": ch += sys.stdin.read(2) # 上箭头:翻上一条历史 if ch == "\x1b[A": if history_pointer < len(COMMAND_HISTORY): history_pointer += 1 # 清空当前已输入内容 sys.stdout.write("\b" * len(current_input) + " " * len(current_input) + "\b" * len(current_input)) # 替换为历史内容 current_input = list(COMMAND_HISTORY[len(COMMAND_HISTORY) - history_pointer]) sys.stdout.write("".join(current_input)) sys.stdout.flush() # 下箭头:翻下一条历史 elif ch == "\x1b[B": if history_pointer > 0: history_pointer -= 1 # 清空当前已输入内容 sys.stdout.write("\b" * len(current_input) + " " * len(current_input) + "\b" * len(current_input)) # 指针为0时清空输入,否则替换为对应历史 current_input = [] if history_pointer == 0 else list(COMMAND_HISTORY[len(COMMAND_HISTORY) - history_pointer]) sys.stdout.write("".join(current_input)) sys.stdout.flush() # 退格键:删除最后一个输入字符 elif ch == "\x7f": if len(current_input) > 0: current_input.pop() sys.stdout.write("\b \b") sys.stdout.flush() # 回车键:结束输入 elif ch in ("\r", "\n"): sys.stdout.write("\n") sys.stdout.flush() input_result = "".join(current_input) # 可在此处添加逻辑,将本次输入加入命令历史 return input_result # 普通可打印字符:直接追加显示 else: current_input.append(ch) sys.stdout.write(ch) sys.stdout.flush() finally: # 无论程序是否异常,都恢复原始终端属性,避免终端工作异常 termios.tcsetattr(fd, termios.TCSADRAIN, old_terminal_settings) # 示例调用 if __name__ == "__main__": user_input = custom_input() print(f"输入结果:{user_input}")
使用说明
- 直接运行代码即可测试效果,上下箭头可切换示例历史记录,按键无需回车即可输入,回车后返回输入内容
- 可修改
custom_input的prompt参数自定义输入提示语 - 替换
COMMAND_HISTORY为你自己的历史读写逻辑即可对接业务需求 - 输入过程中按Ctrl+C可正常退出,终端属性会自动恢复
内容的提问来源于stack exchange,提问作者Oliver Williams
相关产品推荐
相关产品推荐

