【问题标题】:How can I use mutually exclusive group with positional arguments? [duplicate]如何将互斥组与位置参数一起使用? [复制]
【发布时间】:2019-09-13 11:08:17
【问题描述】:

我想要实现的是: --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 但是“*”是一种可选的,不是吗?

【问题讨论】:

    标签: python-3.x argparse


    【解决方案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=[])
    

    可能已经在错误/问题中讨论了为什么以这种方式编码,但我不记得任何细节。

    几年前这让我很困惑:

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

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

    【讨论】:

      猜你喜欢
      • 2013-03-29
      • 2017-01-03
      • 2013-03-09
      • 1970-01-01
      • 1970-01-01
      • 2019-02-16
      • 2011-12-26
      • 1970-01-01
      • 2016-05-04
      相关资源
      最近更新 更多