argparse:针对位置参数的个别选择的使用情况报告?

时间:2012-03-11 07:34:21

标签: python argparse

我正在尝试重构程序以使用新标准的argparse模块。鉴于下面的结构,我应该使用choices作为主要位置参数,subcommands还是其他方法?

foo [OPTION]... COMMAND [PACKAGE(S)]...

Commands:
    available -  show packages available to be installed
    install   -  download and install packages, including dependencies
    remove    -  uninstall packages
    ...snip
    version   -  display installed version of package

Options:
    -d,--download          download only
    -i,--ini=FILE          use alternate setup.ini
    ...snip

选择示例,简明扼要清除,但没有使用每个命令的帮助:

parser = argparse.ArgumentParser()
commands = "available install remove ... version".split()
parser.add_argument('command', choices=commands, 
    help="generic help for all 12 commands goes here")

选择在逻辑上与程序更加协调,因为命令行上的命令在所有这些命令之后基本相同。虽然子命令似乎希望我将每个命令作为世界主要对待自己并且涉及代码的3倍。然而,似乎没有一种方法可以显示选择中每个选项的用法(?)也许还有第三条路线我没有看到?

我正在使用python 2.7。

1 个答案:

答案 0 :(得分:3)

我选择sub-commands选项。

您不一定需要编写更多代码:构建命令类,每个类都带有自己的设置(在需要时使用继承),在Main cli类中实例化主解析器,然后将其交给命令将关心添加/设置自己的subparser

答案很简短,但如果不清楚,请告诉我,我会添加一个代码示例。


粗略示例

您应该将命令构建为类:

class Install(BaseCommand):

    help = "download and install packages"

    @classmethod
    def interface(cls, cmd_parser):
        cmd_parser.add_argument('--foo')
        cmd_parser.set_defaults(cmd=cls)    # this line is very important

    def start(self, foo=None):
        # command execution

您的命令行界面也应该是一个类:

class Main(BaseCli):

    def __init__(self):
        self.commands = [Install]   # just the command classes

        self._parser = argparse.ArgumentParser()
        self._subparsers = self._parser.add_subparsers()

    def load_interface(self):
        for cmd in self.commands:
            cmd_parser = self.add_command_parser(help=cmd.help)
            cmd.interface(cmd_parser)

    def add_command_parser(self, *args, **kwargs):
        return self._subparsers.add_parser(*args, **kwargs)

    def parse_args(self, args=None, namespace=None):
        return self._parser.parse_args(args, namespace)

    def start_session(self, namespace):
        # this will instantiate the appropriate command class
        cmd = namespace.cmd()
        # and call its start method with the user args
        cmd.start(**namespace.__dict__)

要像这样使用:

cli = Main()
cli.load_interface()
args = cli.parse_args()
cli.start_session(args)

请注意,通过这种方法,您将拥有所有的继承权力! :)