这就是我喜欢在我的命令行工具 Python 脚本中这样做的方式。
我有一个代表工具的主类:
class MyToolCommandLineDriver(object):
@classmethod
def subcommand_map(cls):
# create a mapping of subcommand names to classes
return subcommand_map
@classmethod
def run(cls):
subcommand_map = cls.subcommand_map()
parser = argparse.ArgumentParser(description='Some Tool')
parser.add_argument('--some_global_option', help='Some Help')
subparsers = parser.add_subparsers(title='Subcommands', dest='subcommand_name')
for subcommand_name, subcommand_class in subcommand_map.items():
subparser = subparsers.add_parser(subcommand_name, help=subcommand_class.__doc__)
subcommand_class.configure_argument_parser(subparser)
if __name__ == "__main__":
MyToolCommandLineDriver.run()
每个subcommand_class 项目都派生自一个公共基类,并有机会配置自己的解析器:
class AbstractSubcommand(object):
@classmethod
def configure_argument_parser(cls, parser):
pass
class SubcommandFooBar(AbstractSubcommand):
@classmethod
def configure_argument_parser(cls, parser):
parser.add_argument('some_argument', nargs='+', help='Some help')
您可以在此处查看完整示例:https://github.com/liyanage/git-tools/blob/master/githelper/githelper.py
这是我制作的基于子命令的工具。此设置允许每个子命令定义其特定参数,并且还可以在顶层免费生成有用的使用消息:
$ githelper.py -h
usage: githelper.py [-h] [--root_path ROOT_PATH] [--verbose]
{status,reset-master-to-svn-branch,svn-conflicts,clone-externals,tree,svn-lineage,svn-diff,branch,each,svn-delete-resolve,svn-mergeinfo,svn-rebase,foo,checkout}
对于每个子命令:
$ githelper.py clone-externals -h
usage: githelper.py clone-externals [-h] svn_url checkout_directory
positional arguments:
svn_url The toplevel SVN repository to clone
checkout_directory The path to the sandbox directory to create