【问题标题】:Python - Circumvent argparse nargs errorPython - 规避 argparse nargs 错误
【发布时间】:2017-08-20 00:40:54
【问题描述】:

我有一个像这样工作的程序:

prog.py filename -r

使用我给的默认默认值

prog.py filename -r 0 500 20

使用0, 500 and 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 __init__ 并修改该函数中的某些内容。是否有可能在nargs='*' 时得到与上面代码相​​同的结果,但使用nargs=3 时得到的结果?

【问题讨论】:

  • 如果您根本不提供-r 会发生什么?
  • 你之前的问题stackoverflow.com/q/42928410
  • @hpaulj 我的程序是这样工作的,你输入一个文件名,然后输入你想要运行的函数的标志。当它只有 -r 时,rdist 函数使用标准值运行。当您输入带有值的 -r 时,rdist 函数将使用这些值运行。我虽然可以将此作为一个新问题发布,因为现在我的问题更多关于自定义操作和 nargs 错误。

标签: python argparse


【解决方案1】:

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

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

如果我设置nargs=3(不带引号),那么它对我有用:

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])

这就是你要找的吗?

这里的诀窍是,如果 nargs 不是特殊字符之一('?'、'*'、'+' 等),那么它必须是整数,而不是字符串。

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

【讨论】:

  • 感谢您的回答,但我认为您有点误解了我的问题。为了清楚起见,请参阅上面的 cmets :)
  • 这是一个很好的收获
【解决方案2】:

正如我在上一个问题中指出的那样,只需省略 -r 即可将 default 放入 args 命名空间中。你不必做任何特别的事情。

nargs='?' 有第三个选项,const

您的自定义操作有点像这样,当-r 不带任何字符串使用时,它会为命名空间分配一个自定义值。

解析大致如下:

  • 为命名空间分配默认值
  • 依次循环输入、处理位置和选项
  • 对于每个参数,调用它的Action.__call__
  • values 传递的数量取决于nargs 参数

您的自定义RdistAction 无法控制values 的数量,除非通过其nargs 属性。 nargs=3 表示正好 3,nargs='*' 表示“尽可能多地给我”(即 0 或到末尾或到下一个标志)。

optparse 中,Action 给出了所有剩余的argv 字符串,并且可以根据需要使用任意数量的字符串。但在argparse 中,分配是在更高级别完成的,Action 使用它给定的内容。

我在 Python 错误/问题中探索了扩展 nargs 以包含 regex 之类的范围,例如[0,3]。但这需要更改解析器的核心。

你还没有解释为什么需要这个 -r 选项。

【讨论】:

  • 但问题是,我不想省略 -r 来获取默认值。这个自定义操作现在可以为我做这件事,除了我必须使用 nargs='*'。我基本上只是好奇是否可以使用 nargs=3 实现相同的目标并规避 nargs 错误。请参阅上面关于为什么我需要裸 -r 选项的说明。
  • 我基本上在寻找:if values &lt; 3: set default values to ..... else: use given values 但这在__call__ 函数中设置时不起作用,这就是为什么我认为如果在__init__ 中执行类似的操作它可能会起作用。但是,正如您在回答中所说的那样,您的意思是说这样做需要更改 argparse 模块吗?
  • bugs.python.org/issue11354 是探索将nargs 概括为包含范围的错误/问题。这不是一个微不足道的补丁。
猜你喜欢
  • 2014-10-11
  • 1970-01-01
  • 2018-06-29
  • 2021-11-27
  • 2013-10-14
  • 2012-01-27
  • 2016-11-01
  • 2015-07-25
  • 2023-01-22
相关资源
最近更新 更多