接受固定数量的参数,或者不接受使用固定数量默认值的参数

2024-04-29 15:45:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望允许2个参数或0个参数,并返回默认值。我想应该这样做

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('myargs', nargs=2, default=['foo', 'bar'])

但是,这会引发除2个参数以外的任何参数(因此从不调用默认值):

print(parser.parse_args(['a', 'b'])) # 2 arguments accepted
print(parser.parse_args([])) # throws

我的问题是,(如何)在没有额外代码的情况下做到这一点。也就是说,我想找到比此解决方案更优雅、更默认的argparse

import argparse

def parse(args):

    parser = argparse.ArgumentParser()
    parser.add_argument('myargs', nargs='*', default=['foo', 'bar'])
    a = parser.parse_args(args)

    if len(a.myargs) != 2:
        raise IOError('Incorrect number of arguments')

    return a

print(parse([])) # defaults
print(parse(['a', 'b'])) # 2 arguments accepted
print(parse(['a', 'b', 'c'])) # throws (as excepted)

Tags: importadddefaultparser参数fooparseargparse
2条回答

简要描述一下argparse解析的工作原理可能会有所帮助

值收集在namespace对象中。解析开始时,default值都放在namespace中。然后,当在用户输入中遇到参数时,将按照add_argument中的指定以及namespace中的值对其进行解析,并覆盖默认值

当看到标记时,会解析标记的参数,例如“foobar”,但需要像您这样的位置,并采用nargs指定的字符串的确切数目。在这种情况下,它将使用2个字符串。因此,对于这个定义,default参数是无用的

对于nargs='*',任何数量的字符串都满足它。0字符串的大小写得到特殊处理,并将默认值放在namespace

在优雅中没有关于在解析后添加检查的内容。可以通过以下方式简化错误消息:

if len(a.myargs) != 2:
    parser.error('Incorrect number of arguments')

optparse这样的旧解析器处理所有标记的参数,并在extras中返回其余参数供您处理argparse处理那些extras。使用固定的nargs处理位置是最简单的。一个带有变量nargs的位置变量通常可以正常工作,但很难使用多个。如果您使用*指定了两个操作,那么解析器应该如何分配字符串

是的,您可以定义自定义的Action类来处理特殊情况,但结果通常不如简单的解析后检查优雅(IMO)。我不会因为聪明而加分:)

argparse中,不带前缀的参数(默认前缀为-表示缩写,默认前缀为表示完整参数名)被视为强制参数。所以,如果你想有一个可选的参数,你可以这样做:

parser = argparse.ArgumentParser()
parser.add_argument(' myargs', nargs=2, default=['foo', 'bar'])

在本例中,如果未传递任何参数,则其工作方式与预期相同:

print(parser.parse_args([]))

Namespace(myargs=['foo', 'bar'])

另一方面,如果提供相同的值:

print(parser.parse_args([' myargs', 'a', 'b']))

Namespace(myargs=['a', 'b'])

如果在myargs之后传递了错误数量的参数,则会引发错误:

print(parser.parse_args([' myargs', 'a']))

usage: scratch_2.py [-h] [ myargs MYARGS MYARGS]
<your script name>: error: argument  myargs: expected 2 arguments

另一种(更长的)方法是定义自定义操作来解析参数:

class CustomParsePositional(argparse.Action):
    """Action to parse arguments with a custom processing"""
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        super().__init__(option_strings, dest, nargs='*', **kwargs)
        self._custom_nargs = len(kwargs.get('default', []))
    def __call__(self, parser, namespace, values, option_string=None):
        if len(values) != self._custom_nargs:
            parser.error('Incorrect number of arguments')
        namespace.__setattr__(self.dest, values)

parser = argparse.ArgumentParser()
parser.add_argument('myargs', default=['foo', 'bar'], type=str, action=CustomParsePositional)

在这种情况下,期望值的数量由add_argumentdefault参数中的项数推断出来。这里有一些例子:

print(parser.parse_args(['a', 'b']))
print(parser.parse_args([]))
print(parser.parse_args(['a']))


Namespace(myargs=['a', 'b'])
Namespace(myargs=['foo', 'bar'])
usage: scratch_2.py [-h] [myargs [myargs ...]]
<your script name>: error: Incorrect number of arguments

如果你传递了3个值,你也会得到一个错误:

print(parser.parse_args(['a', 'b', 'c']))

usage: scratch_2.py [-h] [myargs [myargs ...]]
<your script name>: error: Incorrect number of arguments

相关问题 更多 >