如何在Python中实现多级CLI?

6 投票
2 回答
6056 浏览
提问于 2025-04-16 05:43

我正在尝试做一个命令行界面(CLI),最好是用Python写的。我需要一个多层级的命令行界面,并且希望能有按下Tab键自动补全的功能。

我查看了Python标准库里的cmd模块和readline模块,它们都有“complete”这个功能(用于实现Tab键补全)。

但是它们都有些不足,我还没有弄明白怎么处理多个层级,比如:

level1
level2
    level2_subcommand_1
    level2_subcommand_2
level3
    level3_subcommand_1

举个例子:如果我输入:

cmd> level2

当我按下Tab键时,我希望能看到level2_subcommand_1和level2_subcommand_2出现,但不想看到level1和level3。

我用cmd库和readline都没能做到这一点。

2 个回答

0

argpext模块来自pypi,它可以在命令行界面中实现多级子命令的功能。现在还不支持自动补全(可能以后会有?)。

13

在我使用 Python 2.6.5 的 cmd 模块时,一切都运行得很好。下面是我用来测试的示例代码:

import cmd

class MyInterpreter(cmd.Cmd):
    def do_level1(self, args):
        pass

    def do_level2_subcommand_1(self, args):
        pass

    def do_level2_subcommand_2(self, args):
        pass

    def do_level3_subcommand_1(self, args):
        pass

MyInterpreter().cmdloop()

当我在命令行输入“level2”然后按下 Tab 键时,这一行会扩展为 level2_subcommand_,因为这是所有补全建议的共同前缀。当我再次按 Tab 键而不输入任何内容时,下一行会正确显示 level2_subcommand_1level2_subcommand_2。这就是你想要的效果吗?

对于子命令的情况,另一种变体是为它们创建一个子解释器:

class SubInterpreter(cmd.Cmd):
    prompt = "(level2) "

    def do_subcommand_1(self, args):
        pass

    def do_subcommand_2(self, args):
        pass

    def do_quit(self, args):
        return True
    do_EOF = do_quit

class MyInterpreter(cmd.Cmd):
    def do_level1(self, args):
        pass

    def do_level2(self, args):
        sub_cmd = SubInterpreter()
        sub_cmd.cmdloop()

    def do_level3(self, args):
        pass

上面的变体会在你的“主”解释器中给你 level1level2level3。当你在主解释器中调用 level2 时,它会构建子解释器并调用它的命令循环。子解释器的提示符与主解释器不同,所以你总是能分辨出自己在哪个解释器中。子解释器会给你 subcommand_1subcommand_2subcommand_3quitquit 会让你返回主解释器,EOF 字符也是如此。

撰写回答