如何将互斥组与位置参数一起使用?

时间:2019-04-24 08:06:42

标签: python-3.x argparse

我要实现的是: --read_file <some file>positional argument只能指定其中一个。 prog --read_file inputfile可以。 prog --read_file也可以。 prog input1 input2 ...可以。 prog input1 --read_file不好。

所以我这样做了:

readlist_group.add_argument(
    "--read_file",
    dest="read_file",
    metavar="file_to_read",
    help="If enabled, input will be ignored and list will be read from given file. [default: %(default)s][const: %(const)s]",
    type=argparse.FileType("r"),
    default=None,
    const=sys.stdin,
    nargs="?",
)

readlist_group.add_argument(
    dest="inputs",
    help="inputs",
    metavar="input",
    type=str,
    nargs="*",
)

但是,我得到了ValueError: mutually exclusive arguments must be optional,但是“ *”是可选的吗?

1 个答案:

答案 0 :(得分:1)

除非提供默认值,否则“ *”为“必需”。

In [15]: parser=argparse.ArgumentParser()                                       
In [16]: gp = parser.add_mutually_exclusive_group()                             
In [17]: a = gp.add_argument('-r', nargs='?', default='def', const='con')       
In [18]: b = gp.add_argument('foo', nargs='*', default=[])                      
In [19]: parser.print_help()                                                    
usage: ipython3 [-h] [-r [R] | foo [foo ...]]

positional arguments:
  foo

optional arguments:
  -h, --help  show this help message and exit
  -r [R]

我应该查看代码和/或文档以了解原因。

In [22]: parser.parse_args([])                                                  
Out[22]: Namespace(foo=[], r='def')
In [23]: parser.parse_args(['-r'])                                              
Out[23]: Namespace(foo=[], r='con')
In [24]: parser.parse_args(['-r','test'])                                       
Out[24]: Namespace(foo=[], r='test')
In [25]: parser.parse_args(['test'])                                            
Out[25]: Namespace(foo=['test'], r='def')
In [26]: parser.parse_args(['test','1','2'])                                    
Out[26]: Namespace(foo=['test', '1', '2'], r='def')
In [27]: parser.parse_args(['test','1','2','-r'])                               
usage: ipython3 [-h] [-r [R] | foo [foo ...]]
ipython3: error: argument -r: not allowed with argument foo

In [28]: parser.parse_args(['-r','a','b'])                                      
usage: ipython3 [-h] [-r [R] | foo [foo ...]]
ipython3: error: argument foo: not allowed with argument -r

确定,在代码中:

def _get_positional_kwargs(self, dest, **kwargs):
    # make sure required is not specified
    if 'required' in kwargs:
        msg = _("'required' is an invalid argument for positionals")
        raise TypeError(msg)

    # mark positional arguments as required if at least one is
    # always required
    if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
        kwargs['required'] = True
    if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
        kwargs['required'] = True

    # return the keyword arguments with no option strings
    return dict(kwargs, dest=dest, option_strings=[])

在bug /问题中可能已经讨论了为什么要这样编码,但是我不记得任何细节了。

几年前,这使我感到困惑:

https://bugs.python.org/issue26235(需要记录)

How can I create an argparse mutually exclusive group with multiple positional parameters?