argsparse用于解析python中的嵌套可选参数

时间:2015-09-28 21:24:04

标签: python python-2.7 argparse args

我正在尝试为我的python脚本编写解析,其中命令参数应按以下顺序排列,

输出 cli unmount [-h] -f FS_NAME [-n NODE_SPEC] [--evict [--force]]]

除了最后一个命令之外,我能够编写其余命令的代码。 [--evict [--force]]。这意味着--force参数仅在--evict给出时才适用。

parser = argparse.ArgumentParser('CLI demo')
sub_parser = parser.add_subparsers()
unmount = sub_parser.add_parser('unmount')
unmount.add_argument("-f", "--fs", dest="fs_name", required=True, help="filesystem name.")
unmount.add_argument("-n", "--nodes", dest="nodes", metavar='NODE_SPEC', help="pdsh style nodes hostnames (If this parameters ")

这是我将可选子参数--force添加到可选父参数--evict

的两种方法。

方法1:

evict_parser = unmount.add_subparsers()
evict = evict_parser.add_parser("--evict", help="evict lustre clients before unmount.")
evict.add_argument("--force", dest="force", action="store_true", default=False, help="force mode for evict lustre clients.")
parser.parse_args()

方法2:

parent_cmd_parser = argparse.ArgumentParser(add_help=F)
parent_cmd_parser.add_argument("--force", dest="force", action="store_true", default=False, help="force mode for evict lustre clients.")
evict_parser = unmount.add_subparsers()
evict = evict_parser.add_parser("--evict",  help="evict lustre clients before unmount.", parents=[parent_cmd_parser])

不幸的是没有人工作。在第一种情况下,我没有得到所需的帮助输出/使用帮助,在第二种情况下隐藏了--force参数。

2 个答案:

答案 0 :(得分:1)

argparse不直接支持相互依赖的参数。

只需将--force添加为常规参数,文档仅在--evict给出时适用,并在--force使用--evict时给出错误{ {1}}:

if args.force and not args.evict:
    parser.error('--force can only be used together with --evict')

答案 1 :(得分:0)

另一种选择是使用--evict定义nargs='?',并定义defaultconst

parser.add_argument('--evict', nargs='?', default='noEvict', const='EvictWOArgument')

然后args.evict将是' noEvict',' EvictWOArgument',或者用户提供的字符串(例如' force')。您可以选择方便的任何值和解释。您甚至可以使用'选择':

In [2]: parser=argparse.ArgumentParser()    
In [4]: parser.add_argument('-e','--evict',nargs='?',choices=['force'],default=False, const=True)

In [5]: parser.parse_args([])
Out[5]: Namespace(evict=False)

In [6]: parser.parse_args(['-e'])
Out[6]: Namespace(evict=True)

In [7]: parser.parse_args(['-e','test'])
usage: ipython3.5 [-h] [-e [{force}]]
ipython3.5: error: argument -e/--evict: invalid choice: 'test' (choose from 'force')
...

In [8]: parser.parse_args(['-e','force'])
Out[8]: Namespace(evict='force')

如果http://bugs.python.org/issue9334中的补丁已经实施,则可以定义' - 强制'作为choice。目前,解析器在解析的早期分类,例如字符串和选项标志。这样的使用也会让最终用户感到困惑 - --force是可选的,可以去任何地方,还是必须遵循--evict的参数?