python - 如何创建具有多个位置参数的 argparse 互斥组?

标签 python command-line-arguments argparse

我正在尝试解析命令行参数,使得以下三种可能性成为可能:

script
script file1 file2 file3 …
script -p pattern

因此,文件列表是可选的。如果指定了 -p pattern 选项,则命令行上不能有任何其他内容。以“用法”格式说,它可能看起来像这样:

script [-p pattern | file [file …]]

我想用 Python 的 argparse 模块来做这个的方法是这样的:

parser = argparse.ArgumentParser(prog=base)
group = parser.add_mutually_exclusive_group()
group.add_argument('-p', '--pattern', help="Operate on files that match the glob pattern")
group.add_argument('files', nargs="*", help="files to operate on")
args = parser.parse_args()

但是 Python 提示我的位置参数需要是可选的:

Traceback (most recent call last):
  File "script", line 92, in <module>
    group.add_argument('files', nargs="*", help="files to operate on")
…
ValueError: mutually exclusive arguments must be optional

但是argparse documentation表示 nargs"*" 参数意味着它是可选的。

我也找不到任何其他 nargs 的值来解决这个问题。我最接近的是使用 nargs="?",但它只抓取一个文件,而不是任何数字的可选列表。

是否可以使用 argparse 来组合这种参数语法?

最佳答案

简答

*位置添加一个default

引发错误的代码是,

    if action.required:
        msg = _('mutually exclusive arguments must be optional')
        raise ValueError(msg)

如果我将 * 添加到解析器,我会看到设置了 required 属性:

In [396]: a=p.add_argument('bar',nargs='*')
In [397]: a
Out[397]: _StoreAction(option_strings=[], dest='bar', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [398]: a.required
Out[398]: True

而对于 ? 则为 False。我将在代码中进一步挖掘以了解差异的原因。它可能是错误或被忽视的“功能”,或者可能有充分的理由。 “可选”位置的一个棘手的事情是没有答案是一个答案,也就是说,一个空的值列表是有效的。

In [399]: args=p.parse_args([])
In [400]: args
Out[400]: Namespace(bar=[], ....)

所以 mutually_exclusive 必须有一些方法来区分默认的 [] 和真实的 []

现在我建议使用 --files,如果您希望 argparse 执行互斥测试,这是一个带标记的参数而不是位置参数。


设置位置的 required 属性的代码是:

    # mark positional arguments as required if at least one is
    # always required
    if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
        kwargs['required'] = True
    if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
        kwargs['required'] = True

所以解决方案是为 *

指定一个默认值
In [401]: p=argparse.ArgumentParser()
In [402]: g=p.add_mutually_exclusive_group()
In [403]: g.add_argument('--foo')
Out[403]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [404]: g.add_argument('files',nargs='*',default=None)
Out[404]: _StoreAction(option_strings=[], dest='files', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [405]: p.parse_args([])
Out[405]: Namespace(files=[], foo=None)

默认值甚至可以是 []。解析器能够区分您提供的默认值和未提供默认值时使用的默认值。

糟糕 - default=None 是错误的。它通过了 add_argumentrequired 测试,但产生了 mutually_exclusive 错误。细节在于代码如何区分用户定义的默认值和自动的默认值。因此,请使用除 None 之外的任何内容。

我在文档中没有看到任何关于此的内容。我必须检查错误/问题才能看到该主题已被讨论。它之前也可能出现在 SO 上。

关于python - 如何创建具有多个位置参数的 argparse 互斥组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35044288/

相关文章:

python - 为什么 IPython.display.Image 没有显示在输出中?

python - 在Python 2.7中打印X型图案

python - 使用 pyInstaller 2.0 创建具有特定参数的 python 脚本的可执行文件

python - 未提供值时命令行参数的默认值

python - 对一个对象执行某些操作会对同一类的所有对象执行相同的操作吗?

Python BeautifulSoup 仅段落文本

ascii - 如何在可执行文件的参数中包含回车符?

java - 不同数量的命令行参数

python - 使用 parse_known_args() 时推迟退出 --help

python - 如何在python argparse中使参数可选