1. 实现一个支持子命令的CLI框架

实现一个支持子命令的CLI框架 学习卡片

任务说明

构建一个轻量级CLI框架,支持注册子命令(add、remove、list)并正确分发调用,对未知命令给出友好错误提示。框架核心包含命令注册表、参数解析与分发逻辑,不依赖第三方库,使用Python标准库实现。

核心实现

import sys
import shlex

class CLIApp:
    def __init__(self, app_name="app"):
        self.app_name = app_name
        self.commands = {}

    def register(self, name, handler, help_text=""):
        """注册子命令及其处理函数"""
        self.commands[name] = {
            "handler": handler,
            "help": help_text
        }

    def run(self, argv=None):
        """解析参数并分发到对应子命令"""
        if argv is None:
            argv = sys.argv[1:]

        if not argv:
            self.print_help()
            return 1

        cmd_name = argv[0]
        cmd_args = argv[1:]

        if cmd_name in ("-h", "--help", "help"):
            self.print_help()
            return 0

        if cmd_name not in self.commands:
            print(f"错误: 未知命令 '{cmd_name}'")
            print(f"可用命令: {', '.join(self.commands.keys())}")
            print(f"使用 '{self.app_name} help' 查看帮助")
            return 1

        try:
            return self.commands[cmd_name]["handler"](cmd_args)
        except TypeError as e:
            print(f"参数错误: {e}")
            return 1

    def print_help(self):
        """打印所有已注册命令的帮助信息"""
        print(f"用法: {self.app_name} <命令> [参数...]")
        print("\n可用命令:")
        for name, info in self.commands.items():
            help_text = info["help"] or "无描述"
            print(f"  {name:10s} {help_text}")

# ---- 具体子命令实现 ----
def cmd_add(args):
    """add 命令: 添加项目"""
    if len(args) != 1:
        print("用法: app add <项目名>")
        return 1
    item = args[0]
    # 实际项目中可在此写入存储
    print(f"已添加: {item}")
    return 0

def cmd_remove(args):
    """remove 命令: 移除项目"""
    if len(args) != 1:
        print("用法: app remove <项目名>")
        return 1
    item = args[0]
    print(f"已移除: {item}")
    return 0

def cmd_list(args):
    """list 命令: 列出所有项目"""
    if args:
        print("用法: app list (无参数)")
        return 1
    # 演示数据,实际可读取存储
    items = ["项目A", "项目B", "项目C"]
    if not items:
        print("(空列表)")
    else:
        for i, item in enumerate(items, 1):
            print(f"{i}. {item}")
    return 0

def main():
    app = CLIApp(app_name="app")
    app.register("add", cmd_add, "添加一个新项目")
    app.register("remove", cmd_remove, "移除一个项目")
    app.register("list", cmd_list, "列出所有项目")
    sys.exit(app.run())

if __name__ == "__main__":
    main()

落地与运行

将上述代码保存为 cli_app.py,在终端执行以下命令验证:

python cli_app.py add 任务1
python cli_app.py list
python cli_app.py remove 任务1
python cli_app.py unknown_cmd
python cli_app.py help

验证方法与判定标准

  • 正常命令:执行 add 任务1 输出“已添加: 任务1”;list 输出编号列表;remove 任务1 输出“已移除: 任务1”。
  • 未知命令:执行 unknown_cmd 应输出“错误: 未知命令 'unknown_cmd'”并列出可用命令,退出码为1。
  • 参数校验:执行 add(无参数)应提示用法并返回1。
  • 帮助信息:执行 help 或 -h 显示全部命令及描述。

以上输出均为代码逻辑直接推出的预期结果,实际执行时以终端显示为准。

CLI框架命令分发流程 python cli_app.py argv[0] = 子命令名 命令存在? in commands 是 调用 handler(args) add/remove/list 否 输出错误 + 可用命令列表 注册表: {"add": handler, "remove": handler, "list": handler}