如何解决接受固定数量的参数,或使用固定数量的默认值不接受参数
我想允许 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
我的问题是,(如何)无需额外代码即可完成此操作。 IE。我想找到比例如这个解决方法更优雅和更默认的 argparse :
import argparse
def parse(args):
parser = argparse.ArgumentParser()
parser.add_argument('myargs',nargs='*','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)
解决方法
在 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,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','bar'],type=str,action=CustomParsePositional)
在这种情况下,预期值的数量由 default
的 add_argument
参数中的项目数推断。这里有一些例子:
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
,
对 argparse
解析工作原理的简要说明可能会有所帮助。
值收集在 namespace
对象中。在解析开始时,default
值都放在 namespace
中。然后,当在用户输入中遇到参数时,它们会按照 add_argument
中的指定进行解析,并将值放置在 namespace
中,覆盖默认值。
标记参数在看到标志时被解析,例如'--foo bar',但需要像您这样的位置,并采用 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)。我不给聪明加分:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。