如何避免arg与argparse的混淆?

时间:2015-12-01 10:24:54

标签: python argparse

在一个名为simulate.py的python脚本中,我有以下参数:

parser.add_argument('-s', '--simulators', nargs='+',
                     help='specify the simulators to use',
                     choices=['s1', 's2', 's3'])
parser_build = subparsers.add_parser('build')
parser_build.add_argument('-o3', '--optim', action='store_true')
parser_run = subparsers.add_parser('run')
parser_run.add_argument('-v', '--verbose', action='store_true')

以下命令行选项:

> ./simulate.py -s s1 s2 build

生成以下错误消息:

simulate.py: error: argument -s/--simulators: invalid choice: 'build'

在这种情况下我应该如何指定模拟器列表,其中我有另一个没有选项前缀的参数(例如-c for exemple)?

1 个答案:

答案 0 :(得分:0)

如下所述:Argparse - do not catch positional arguments with `nargs`.

nargs='+' optional(标记参数)后跟positional有问题。 optional使用所有字符串,positional没有。有一个建议的错误补丁,但它尚未发布。

正常的快速解决方案是使用'--'标记optional及其参数的结尾。其他所有内容都被视为positionals。你也可以在其间放置一些其他标记的参数。

-s需要做出选择,使您的情况复杂化。 positionalsubparsers,也可以选择['build', 'run']。作为一个人,你理解' s2'作为属于-s和' build'的选择作为解析器之一。但argparse不会根据选择分配参数;它只使用计数(nargs)。在分配参数后检查choices

我必须查看代码,了解为什么'-s s1 s2 -- build'会引发子分段选择错误。通常' - '被忽略了。但显然subparsers并没有这样做。这是一个特殊的positional Action类。

==========================

我找到了解释您的'--'问题的代码。在将字符串转换为type的函数中,有一个代码块:

    # for everything but PARSER, REMAINDER args, strip out first '--'
    if action.nargs not in [PARSER, REMAINDER]:
        try:
            arg_strings.remove('--')
        except ValueError:
            pass

您的subparsers参数有nargs=PARSER,因此--未被删除。

============================

我认为您需要更改-s,以便它接受固定数量的参数。或者定义一些可以标记其结尾的其他optional,有用与否。如果您想进入argparse胆量,请随时查看链接的bug问题。