如何在Python中创建命令行界面或解释器

6
我已经开发了class1.py、class2.py等文件,并在每个类中实现了函数,例如Operator.py有add、minus、time、divide函数。如何为这些类构建命令行界面?
此外,对于这个CLI,main()内部是否是一个无限循环以进行交互?
CLI如何提供一些反馈,例如建议用户进行下一步操作或输入正确的命令,或者键入--help并检查所有可用命令,就像Bash shell一样?
另外,似乎Python中有optparse模块。是否有一些好的、完整的或高质量的示例展示如何构建CLI?我想借此机会学习如何编写CLI程序。
我已经开发了几个类,还有一个GUI来调用这些类的方法。现在我想要一个CLI,就像GUI一样,来使用这些类。例如,我有像CDContainer(具有addCD、removeCD等方法)、CD(具有play、stop、pause等方法)这样的类,我有一个可以交互的GUI。现在我想要一个CLI,在bash下运行这个CLI并调用createCDContainer、addCD、removeCD命令。
如果我使用cmd
class CDContainerCLI(cmd.Cmd):
            
    def do_CDContainer(self, line):
        print "create CD container"

    def do_addcd(self, line):
        print "add cd into the container"

我该如何在这里添加一些选项?例如,我想要addcd --track 3 --cdname thriller

我认为--track 3 --cdname thrilleraddcd函数的4个参数。如何实现?


1
“我该如何为这些类构建命令行界面?”这个问题很难猜测你的意思。你想要做什么现在做不到?能否提供任何提示或示例? - S.Lott
嗨,S.Lott,请看我添加的关于我想要的最后一段。 - pepero
如果您有另外一个问题,那么您应该将其作为一个独立的问题提出。 - Ignacio Vazquez-Abrams
4个回答

5
继承自cmd.Cmd,必要时覆盖各种方法。

嗨,lgnacio,非常感谢您的建议。我尝试了cmd.Cmd,它非常好用。但是有一个问题,如何添加选项。例如,如果我定义do_login,如何添加--username、--password作为选项? - pepero

1

1

我不确定你想要什么:看起来你想要构建一个交互式 shell,但你也提到了 optparse,它是设计用于简化模块接口的创建,可以从系统 shell 中运行,而不是提供自己的 shell。

看起来你确实希望你的模块实现自己的交互式 shell,但也许你还想从命令行访问一些命令,例如通过从 bash 或其他地方调用 your_script the_command --argument value --other-argument。这就是 optparse 的作用,但它已被弃用,推荐使用 argparseargparse 在 Python 2.7 标准库中,并且可以按照标准方式安装(例如作为您的模块的依赖项,或通过 PyPI 等单独安装)以供旧版本的 Python 使用。

argparse 使得将特定选项或子命令链接到代码中的入口点(即函数调用)相对简单。文档非常详细,如果您可能需要创建一些这样的接口,则值得仔细阅读。对于高级用法,您可以通过创建自定义操作来实现一些有趣的功能,并使您的代码更易于管理。


嗨,intuited,感谢您的评论。我添加了一些关于我想要做的具体注释。如果我使用cmd,我可以有cli,但我不知道如何设置选项。 - pepero
我认为cmd不提供任何支持将Python功能导出到系统shell调用的功能;这正是argparse所做的。您需要将实际执行操作的代码放在单独的模块/类中,并从cmdargparse中调用它。看起来您需要使用子命令来获得您想要的结果。但Ignacio是正确的:您应该提出另一个问题,特别是因为您已经接受了与此问题无关的问题。 - intuited

0

我认为他在询问如何在交互式shell中轻松处理可选参数,这样当你使用程序时,它会看起来像这样:

$ myprogram
(Cmd) addcd --track 3 --cdname thriller

运行myprogram会打开它自己的命令提示符,可以向其中输入addcd等命令,以及可选参数,然后进行处理。

我认为最好的方法是使用argparsecmd。不要解析sys.argv,而是将parse_args方法传递给字符串列表。所以类似下面这样:

def do_addcd(self, line):
    parser = argparse.ArgumentParser(prog='addcd')
    parser.add_argument('--track', type=int)
    parser.add_argument('--cdname')

    args = parser.parse_args(line.split())
    newcd = CD(args.track, args.cdname)

像这样做的问题,正如我自己尝试做这种事情时发现的那样,是parse_args倾向于退出整个程序,如果您提供了错误数量的参数或其他错误。在这种用例中期望的行为是简单地返回到您的自定义交互式 shell,但是如果没有一些 hacky workaround 或子类化 ArgumentParser 并覆盖 parse_args,这将不容易实现。


作为解决我上面描述的问题的一个相对干净的解决方案(我刚刚发现),您可以从ArgumentParser派生一个类并覆盖错误方法,以便它不退出而是引发异常,然后可以在Cmd方法中捕获该异常。 - ztangent
这听起来像是一个非常值得的用途,也许值得提出一个功能请求,不要让 Python 就这么退出。 - Stuart Axon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接