Python-规避argparse nargs错误

Python-规避argparse nargs错误,python,argparse,Python,Argparse,我有一个这样的程序: prog.py filename -r 使用我给定的默认值 prog.py filename -r 0 500 20 使用0、500和20 我通过以下方式实现了这一目标: class RdistAction(argparse.Action): def __call__(self,parser,namespace,values,option_string=None): if not values: setattr(names

我有一个这样的程序:

prog.py filename -r
使用我给定的默认值

prog.py filename -r 0 500 20
使用
0、500和20

我通过以下方式实现了这一目标:

class RdistAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        if not values:
            setattr(namespace,self.dest,[0, 1000, 50])
        else:
            setattr(namespace,self.dest,values)

parser = argparse.ArgumentParser()
parser.add_argument("-r", "--rdist", action=RdistAction, nargs='*', type=int)
args = parser.parse_args()
但我想变得固执,因为我最初的目标是将nargs设置为3。但是,当我在上面的代码中使用nargs=3时,我得到一条错误消息,指出应该有3个参数


我在谷歌上搜索了一下,从结果中我的直觉告诉我必须添加
def\uuuu init\uuu
,并修改该函数中的某些内容。当
nargs='*'
时,是否有可能得到与上面代码中相同的结果,但使用
nargs=3
替代?

如果我将您的
add_参数
行更改为
nargs='3'
,我想我得到了您所犯的错误:

Traceback (most recent call last):
  File "python", line 12, in <module>
ValueError: length of metavar tuple does not match nargs
给予

这就是你要找的吗

这里的技巧是,如果NARG不是特殊字符(“?”、“*”、“+”,等等)之一,那么它需要是一个整数,而不是字符串


请注意,这确实指出了这一点。

正如我在上一个问题中指出的那样,只要省略
-r
就可以将
默认值
放在args名称空间中。你不必做任何特别的事

nargs=“?”
有第三个选项,
const

您的自定义操作的行为有点类似于此,因为当使用
-r
时,它会在没有任何字符串的情况下为命名空间分配一个自定义值

解析大致如下:

  • 为命名空间指定默认值
  • 按顺序循环输入、处理位置和选项
  • 对于每个参数,调用其
    操作
  • 传递的
    值的数量取决于
    nargs
    参数
您的自定义
rdistation
无法控制
值的数量,除非通过其
nargs
属性
nargs=3
表示正好是3,
nargs='*'
表示“您可以给我多少”(即0或到最后或到下一个标志)

optpasse
中,一个操作将给出所有剩余的
argv
字符串,并且可以使用任意数量的字符串。但是在
argparse
中,分配是在更高的级别上完成的,操作使用给定的内容

我在Python bug/issue中探索了扩展
nargs
以包括
regex
类似的范围,例如
[0,3]
。但这需要对解析器的核心进行更改


您还没有解释为什么需要这个裸露的
-r
选项。

如果您根本不提供
-r
该怎么办?您前面的问题@hpaulj我的程序是这样工作的,您输入一个文件名,然后输入要运行的函数的标志。当它仅为-r时,rdist函数使用标准值运行。当您使用值输入-r时,rdist函数将使用这些值运行。我想我可以把它作为一个新问题发布,因为现在我的问题更多的是关于自定义操作和nargs错误。但问题是,我不想忽略-r来获得默认值。这个自定义操作现在为我实现了这一点,但我必须使用nargs='*'。我基本上只是好奇,是否有可能在nargs=3的情况下实现同样的效果,并绕过nargs错误。请参阅上面的解释,了解我为什么需要bare-r选项。我基本上是在寻找:
如果值<3:将默认值设置为。。。。。其他:使用给定的值,但在
\uuuu call\uuuu
函数中设置时不起作用,这就是为什么我认为如果在
\uuu init\uuuu
中执行类似操作,它可能会起作用。但是,正如您在回答中所说的,您的意思是这样做需要更改argparse模块吗?是探索将
nargs
推广到包括范围的bug/问题。这不是一个小补丁。谢谢你的回答,但我想你误解了我的问题。为了清楚起见,请参见上面的评论:)这是一个很好的捕获
import argparse

class RdistAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
      if not values:
        setattr(namespace,self.dest,[0, 1000, 50])
      else:
        setattr(namespace,self.dest,values)

parser = argparse.ArgumentParser()
parser.add_argument("-r", "--rdist", action=RdistAction, nargs=3, type=int)
print parser.parse_args('-r 0 500 20'.split())
Namespace(rdist=[0, 500, 20])