1. readline 是什么? #

场景 推荐方式
问一句、答一句 input()
反复输入命令(REPL) readline + 循环
复杂表单式 CLI 第三方库如 questionary

2. 前置知识 #

# 尝试导入 readline,检测环境是否支持
try:
    # 导入交互式行编辑库
    import readline
    # 标记当前环境支持 readline
    HAS_READLINE = True
# 捕获导入失败异常
except ImportError:
    # 标记当前环境不支持 readline
    HAS_READLINE = False
pip install pyreadline3
pip install prompt_toolkit

3. 命令历史 #

# 导入 readline 模块
import readline
# 导入路径处理工具
from pathlib import Path

# 定义历史文件路径(存放在用户主目录)
HISTORY = Path.home() / ".history"

# 启动时加载历史
# 若历史文件已存在则读取
if HISTORY.exists():
    # 从文件加载命令历史到内存
    readline.read_history_file(HISTORY)

# 使用 try/finally 确保退出时保存历史
try:
    # 提示用户输入并获取姓名
    name = input("你叫什么名字? ")
    # 打印问候语
    print(f"你好,{name}!")
    # 手动将输入加入历史(可选)
    readline.add_history(f"name {name}")
finally:
    # 退出时保存历史
    # 将内存中的命令历史写入文件
    readline.write_history_file(HISTORY)

4. Tab 自动补全 #

# 导入 readline 模块
import readline

# 定义可供 Tab 补全的命令列表
COMMANDS = ["help", "exit", "list", "show"]

# 定义 Tab 补全回调函数
def completer(text, state):
    # 筛选以当前输入开头的命令
    options = [cmd for cmd in COMMANDS if cmd.startswith(text)]
    # 返回第 state 个匹配项,无更多时返回 None
    return options[state] if state < len(options) else None

# 注册补全函数
readline.set_completer(completer)
# 将 Tab 键绑定到补全功能
readline.parse_and_bind("tab: complete")

# 开始一个无限循环,持续读取用户输入
while True:
    # 提示用户输入命令,并将输入内容赋值给 user_input
    user_input = input("请输入命令: ")
    # 判断输入是否为 "exit",若是则跳出循环
    if user_input == "exit":
        break
    # 判断输入是否为 "help",若是则输出所有可用命令
    elif user_input == "help":
        print("可用的命令:", ", ".join(COMMANDS))
    # 判断输入是否为 "list",若是则提示正在列出命令
    elif user_input == "list":
        print("正在列出命令……")
    # 判断输入是否为 "show",若是则提示正在显示命令
    elif user_input == "show":
        print("正在显示命令……")
    # 如果输入的命令未知,则提示未知命令
    else:
        print(f"未知命令:{user_input}")

# 输入 hel 后按 Tab → 自动补全为 help

5. 交互式命令行 #

# 导入 readline 模块
import readline
# 导入路径处理工具
from pathlib import Path

# 定义历史文件路径
HISTORY = Path.home() / ".mycli_history"
# 定义可补全的命令列表
COMMANDS = ["help", "exit", "hello"]

# 若历史文件存在则加载
if HISTORY.exists():
    # 从文件恢复命令历史
    readline.read_history_file(HISTORY)

# 定义 Tab 补全回调函数
def completer(text, state):
    # 筛选以当前输入开头的命令
    opts = [c for c in COMMANDS if c.startswith(text)]
    # 返回第 state 个匹配项
    return opts[state] if state < len(opts) else None

# 注册补全函数
readline.set_completer(completer)
# 启用 Tab 键补全
readline.parse_and_bind("tab: complete")

# 打印欢迎提示信息
print("CLI(输入 help 查看命令,exit 退出)")
# 主循环:持续接收并处理用户输入
while True:
    try:
        # 读取一行输入并去除首尾空白
        line = input(">>> ").strip()
    # 捕获 Ctrl+D(EOF)或 Ctrl+C 中断
    except (EOFError, KeyboardInterrupt):
        # 换行后退出循环
        print()
        break
    # 空行则跳过,继续等待输入
    if not line:
        continue
    # exit 命令退出循环
    if line == "exit":
        break
    # help 命令显示所有可用命令
    if line == "help":
        print("可用命令:", ", ".join(COMMANDS))
    # hello 命令打印 world
    elif line == "hello":
        print("world")
    # 未知命令给出提示
    else:
        print(f"未知命令: {line}")

# 退出前将命令历史保存到文件
readline.write_history_file(HISTORY)
# 打印告别语
print("再见!")

6. 常见错误 #

7. 总结 #

7.1 速查 #

# 导入 readline 模块
import readline

# 启用 Tab 补全
readline.parse_and_bind("tab: complete")
# 注册自定义补全函数
readline.set_completer(my_completer)
# 手动添加一条命令到历史
readline.add_history("某条命令")
# 从文件加载历史记录
readline.read_history_file("~/.history")
# 将历史记录保存到文件
readline.write_history_file("~/.history")

# 使用增强后的 input 读取一行输入
line = input(">>> ")

7.2 最佳实践 #