如何创建具有多个位置参数的argparse互斥组? [英] How can I create an argparse mutually exclusive group with multiple positional parameters?

查看:43
本文介绍了如何创建具有多个位置参数的argparse互斥组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解析命令行参数,以便可能出现以下三种可能性:

I'm trying to parse command-line arguments such that the three possibilities below are possible:

script
script file1 file2 file3 …
script -p pattern

因此,文件列表是可选的.如果指定了-p pattern选项,则命令行上将没有其他内容.以用法"格式表示,可能看起来像这样:

Thus, the list of files is optional. If a -p pattern option is specified, then nothing else can be on the command line. Said in a "usage" format, it would probably look like this:

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

我认为使用Python的argparse模块执行此操作的方式如下:

I thought the way to do this with Python's argparse module would be like this:

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抱怨我的位置参数必须是可选的:

But Python complains that my positional argument needs to be optional:

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文档表示,nargs"*"参数意味着它是可选的.

But the argparse documentation says that the "*" argument to nargs meant that it is optional.

我也无法找到nargs的任何其他值来达到目的.我最接近的是使用nargs="?",但是只能获取一个文件,而不是任意数量的可选列表.

I haven't been able to find any other value for nargs that does the trick either. The closest I've come is using nargs="?", but that only grabs one file, not an optional list of any number.

是否可以使用argparse来构成这种参数语法?

Is it possible to compose this kind of argument syntax using argparse?

推荐答案

简短答案

*位置添加default

引发错误的代码是

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

如果在解析器中添加*,则会看到required属性已设置:

If I add a * to the parser, I see that the required attribute is set:

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.我将在代码中进一步进行挖掘,以了解为什么会有所不同.这可能是错误或被忽略的功能",或者可能有充分的理由.带有可选"位置的棘手的事情是,无答案就是答案,也就是说,空值列表是有效的.

while for a ? it would be False. I'll have dig a bit further in the code to see why the difference. It could be a bug or overlooked 'feature', or there might a good reason. A tricky thing with 'optional' positionals is that no-answer is an answer, that is, an empty list of values is valid.

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

因此,互斥体必须具有某种方法来区分默认[]和真实的[].

So the mutually_exclusive has to have some way to distinguish between a default [] and real [].

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

For now I'd suggest using --files, a flagged argument rather than a positional one if you expect argparse to perform the mutually exclusive testing.

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

The code that sets the required attribute of a positional is:

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

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

The default could even be []. The parser is able to distinguish between the default you provide and the one it uses if none is given.

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

oops - default=None was wrong. It passes the add_argument and required test, but produces the mutually_exclusive error. Details lie in how the code distinguishes between user defined defaults and the automatic ones. So use anything but None.

我在文档中什么都没有看到.我必须检查错误/问题才能看到已讨论的主题.也许以前也有关于SO的.

I don't see anything in the documentation about this. I'll have to check the bug/issues to see it the topic has been discussed. It's probably come up on SO before as well.

这篇关于如何创建具有多个位置参数的argparse互斥组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆