我正在尝试重构程序以使用新标准的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。
答案 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)
请注意,通过这种方法,您将拥有所有的继承权力! :)