具有 nargs 行为的 Python argparse 不正确

Posted

技术标签:

【中文标题】具有 nargs 行为的 Python argparse 不正确【英文标题】:Python argparse with nargs behaviour incorrect 【发布时间】:2013-10-14 05:50:39 【问题描述】:

这是我的 argparse 示例,比如 sample.py

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-p", nargs="+", help="Stuff")
args = parser.parse_args()
print args

Python - 2.7.3

我希望用户在 -p 选项之后提供由空格分隔的参数列表。例如,如果您运行

$ sample.py -p x y 
Namespace(p=['x', 'y'])

但我的问题是当你运行时

$ sample.py -p x -p y
Namespace(p=['y'])

既不在这里也不在那里。我想要以下之一

向用户抛出异常,要求他不要使用 -p 两次,而是将它们作为一个参数提供 假设它是相同的选项并生成一个 ['x','y'] 列表。

我可以看到 python 2.7 没有做这两个让我感到困惑。我可以让 python 执行上面记录的两种行为之一吗?

【问题讨论】:

你当然可以通过继承argparse.Action来让它做你想做的事。 【参考方案1】:

注意:python 3.8 添加了一个action="extend",它将创建所需的 ['x','y'] 列表

要生成 ['x','y'] 的列表,请使用 action='append'。其实它给了

Namespace(p=[['x'], ['y']])

对于每个-p,它会根据nargs='+' 的指示给出一个列表['x'],但append 的意思是,将该值添加到命名空间已有的值中。默认操作只是设置值,例如NS['p']=['x']。我建议查看文档中的 action 段落。

optionals 允许按设计重复使用。它支持appendcount 等操作。通常用户不希望重复使用它们,或者对最后一个值感到满意。 positionals(没有-flag)不能重复(nargs 允许的除外)。

How to add optional or once arguments? 有一些关于如何创建“不重复”参数的建议。一种是创建一个自定义的action 类。

【讨论】:

可惜这个默认不可用... 唉 您对如何指定“只允许使用此选项”有什么建议吗?如何在使用行上标记? 我原以为这是默认设置,即只能指定一次选项。不过我明白你的意思,所有 linux 命令都可以多次使用相同的选项,所以不太确定要与什么进行比较。 但是,如果开发人员忘记执行 nargs=+ ,则存在一个固有问题,argparse 只是假设变量的最新定义。对此可能没有一个简单的答案。我将尝试一些 linux 命令,了解它们如何处理多次指定的相同选项。【参考方案2】:

我遇到了同样的问题。我决定按照 mgilson 的建议使用自定义操作路线。

import argparse
class ExtendAction(argparse.Action):
  def __call__(self, parser, namespace, values, option_string=None):
    if getattr(namespace, self.dest, None) is None:
      setattr(namespace, self.dest, [])
    getattr(namespace, self.dest).extend(values)
parser = argparse.ArgumentParser()
parser.add_argument("-p", nargs="+", help="Stuff", action=ExtendAction)
args = parser.parse_args()
print args

这会导致

$ ./sample.py -p x -p y -p z w
Namespace(p=['x', 'y', 'z', 'w'])

不过,如果库中默认有 action='extend' 选项,那会更整洁。

【讨论】:

如果您将 ArgumentParser 子类化,“注册”您的自定义类可能会很方便。请参阅_ActionsContainer 类。

以上是关于具有 nargs 行为的 Python argparse 不正确的主要内容,如果未能解决你的问题,请参考以下文章

Python argparse:默认参数存储为字符串,而不是列表

添加既改变行为又存储参数的选项

如何在 argparse 中使用带有 nargs='*' 参数的可选位置参数?

argparse:如何允许带有 nargs="*" 和选项的空列表

glibc 中确定宏参数个数的宏__SYSCALL_NARGS 及 可变参数宏__VA_ARGS__

具有自定义元类行为的 Python 元类