1. readline 是什么? #
readline 是 Python 标准库,为交互式命令行提供行编辑和命令历史功能。
- 在支持 readline 的终端中,用户可以用方向键翻阅历史、用退格键编辑,体验类似 Bash。
- 适合需要反复输入命令的交互式 CLI 工具,如简易 Shell、数据库客户端、调试控制台。
- 简单的一次性提问用内置
input() 即可;需要历史记录和 Tab 补全时再用 readline。
| 场景 |
推荐方式 |
| 问一句、答一句 |
input() |
| 反复输入命令(REPL) |
readline + 循环 |
| 复杂表单式 CLI |
第三方库如 questionary |
2. 前置知识 #
readline 主要依赖底层 GNU readline 库,在 Linux/macOS 上通常开箱可用。
- Windows 原生 Python 可能没有 readline 模块,需安装
pyreadline3 或接受功能受限。
- 使用前可用
try: import readline 判断环境是否支持,不支持时降级为普通 input()。
argparse 处理启动参数,readline 处理运行中的交互输入。
try:
import readline
HAS_READLINE = True
except ImportError:
HAS_READLINE = False
pip install pyreadline3
pip install prompt_toolkit
3. 命令历史 #
readline 导入后会自动增强 input(),在交互式终端中可用上下方向键翻阅历史。
readline.add_history(line) 手动将一行加入历史,适合程序代替用户"记住"某些输入。
readline.write_history_file(path) 退出时保存历史,readline.read_history_file(path) 启动时加载。
- 历史文件通常放在用户目录,如
~/.myapp_history,下次启动可继续用上次的命令。
import readline
from pathlib import Path
HISTORY = Path.home() / ".history"
if HISTORY.exists():
readline.read_history_file(HISTORY)
try:
name = input("你叫什么名字? ")
print(f"你好,{name}!")
readline.add_history(f"name {name}")
finally:
readline.write_history_file(HISTORY)
4. Tab 自动补全 #
readline.set_completer(func) 注册补全函数,用户按 Tab 时自动调用。
- 补全函数接收
(text, state) 两个参数,返回第 state 个匹配项,无更多匹配时返回 None。
readline.parse_and_bind("tab: complete") 将 Tab 键绑定到补全功能,这一行必不可少。
- 项目中常用于命令名补全、路径补全、子命令补全等交互式 CLI 场景。
import readline
COMMANDS = ["help", "exit", "list", "show"]
def completer(text, state):
options = [cmd for cmd in COMMANDS if cmd.startswith(text)]
return options[state] if state < len(options) else None
readline.set_completer(completer)
readline.parse_and_bind("tab: complete")
while True:
user_input = input("请输入命令: ")
if user_input == "exit":
break
elif user_input == "help":
print("可用的命令:", ", ".join(COMMANDS))
elif user_input == "list":
print("正在列出命令……")
elif user_input == "show":
print("正在显示命令……")
else:
print(f"未知命令:{user_input}")
5. 交互式命令行 #
- REPL 模式是 readline 最典型的用法:
while True 循环 + input(prompt) + 处理命令。
- 配合 Tab 补全和命令历史,用户可以像使用 Shell 一样操作你的程序。
- 输入
exit 或 quit 时 break 跳出循环,退出前调用 write_history_file 保存历史。
- 不要把
input() 循环和 argparse 混在同一流程:argparse 解析启动参数,循环处理运行时命令。
import readline
from pathlib import Path
HISTORY = Path.home() / ".mycli_history"
COMMANDS = ["help", "exit", "hello"]
if HISTORY.exists():
readline.read_history_file(HISTORY)
def completer(text, state):
opts = [c for c in COMMANDS if c.startswith(text)]
return opts[state] if state < len(opts) else None
readline.set_completer(completer)
readline.parse_and_bind("tab: complete")
print("CLI(输入 help 查看命令,exit 退出)")
while True:
try:
line = input(">>> ").strip()
except (EOFError, KeyboardInterrupt):
print()
break
if not line:
continue
if line == "exit":
break
if line == "help":
print("可用命令:", ", ".join(COMMANDS))
elif line == "hello":
print("world")
else:
print(f"未知命令: {line}")
readline.write_history_file(HISTORY)
print("再见!")
6. 常见错误 #
- 忘记调用
parse_and_bind("tab: complete") 导致 Tab 补全不生效。
- 补全函数参数写错:必须是
(text, state),返回第 state 个匹配项或 None。
- 在 Windows 上直接
import readline 报错,需 try/except 或安装 pyreadline3。
- 把 readline 当作文件行读取工具——读文件用
for line in open(...)。
7. 总结 #
readline 为交互式 CLI 提供命令历史和 Tab 补全,导入后自动增强 input()。
- 核心 API:
set_completer、parse_and_bind("tab: complete")、read/write_history_file。
- 典型模式:
while True + input(">>> ") + 命令分发,输入 exit 退出。
- 简单场景用
input() 即可;跨平台项目注意 Windows 兼容性。
7.1 速查 #
import readline
readline.parse_and_bind("tab: complete")
readline.set_completer(my_completer)
readline.add_history("某条命令")
readline.read_history_file("~/.history")
readline.write_history_file("~/.history")
line = input(">>> ")
7.2 最佳实践 #
- 启动时
read_history_file,退出时 write_history_file
- 补全列表从固定命令表或动态扫描生成,保持精简
- Windows 用 try/except 包裹
import readline,保证降级可用
- 与
argparse 分工:启动参数用 argparse,运行时交互用 readline