简体   繁体   English

argparse:如何配置多项选择,多值,可选参数?

[英]argparse: how to configure multiple choice, multiple value, optional argument?

I'm trying to set up an argument that accepts one or more values from a given list of choices, but is not obligatory.我正在尝试设置一个参数,该参数接受给定选项列表中的一个或多个值,但不是强制性的。 I'm trying this (with a couple of variants that also don't work as expected):我正在尝试这个(有几个变体也不能按预期工作):

parser.add_argument("FLAGS", nargs='*', choices=["X","Y","Z","ALL"])

I expect to get a list of values from the list of choices, or an empty list if nothing was given (that, I think, should be enforced by nargs='*' ).我希望从选择列表中获得一个值列表,或者如果没有给出任何内容,则获得一个空列表(我认为应该由nargs='*'强制执行)。 But regardless of whether I add default="" or not, when I don't pass any argument it fails with:但无论我是否添加default="" ,当我不传递任何参数时,它都会失败:

error: argument FLAGS: invalid choice: []

How to achieve what I need?如何实现我所需要的?

This probably doesn't fit your needs, but you can do it easily with an option like --flags .这可能不符合您的需求,但您可以使用--flags类的选项轻松完成。

parser.add_argument(
    "--flags",
    nargs='*',
    default=[],  # Instead of "None"
    choices=["X", "Y", "Z", "ALL"])

args = parser.parse_args()
print(args)
$ tmp.py
Namespace(flags=[])

$ tmp.py --flags
Namespace(flags=[])

$ tmp.py --flags X
Namespace(flags=['X'])

$ tmp.py --flags X Z
Namespace(flags=['X', 'Z'])

$ tmp.py --flags foobar
usage: tmp.py [-h] [--flags [{X,Y,Z,ALL} ...]]
tmp.py: error: argument --flags: invalid choice: 'foobar' (choose from 'X', 'Y', 'Z', 'ALL')

$ tmp.py --help
usage: tmp.py [-h] [--flags [{X,Y,Z,ALL} ...]]

optional arguments:
  -h, --help            show this help message and exit
  --flags [{X,Y,Z,ALL} ...]

A positional '*' gets some special handling.位置“*”得到一些特殊处理。 Its nargs is satisfied with an empty list (nothing).它的nargs对空列表(无)感到满意。 It's always handled.它总是被处理。 What does it mean to check an empty list of strings against the choices ?根据choices检查一个空的字符串列表是什么意思?

So the get_values() method does:所以get_values()方法会:

    # when nargs='*' on a positional, if there were no command-line
    # args, use the default if it is anything other than None
    elif (not arg_strings and action.nargs == ZERO_OR_MORE and
          not action.option_strings):
        if action.default is not None:
            value = action.default
        else:
            value = arg_strings
        self._check_value(action, value)

where _check_value tests if value is in the choices .其中_check_value测试value是否在choices中。

Such a positional is best used with a valid default .这种位置最好与有效的default一起使用。

In [729]: p=argparse.ArgumentParser()
In [730]: a=p.add_argument("FLAGS", nargs='*', choices=["X","Y","Z","ALL"])
In [731]: p.parse_args([])
usage: ipython3 [-h] [{X,Y,Z,ALL} [{X,Y,Z,ALL} ...]]
ipython3: error: argument FLAGS: invalid choice: [] (choose from 'X', 'Y', 'Z', 'ALL')
...

Testing an empty list against choices fails:针对choices测试空列表失败:

In [732]: a.choices
Out[732]: ['X', 'Y', 'Z', 'ALL']
In [733]: [] in a.choices
Out[733]: False
In [734]: 'X' in a.choices
Out[734]: True

If we set a valid default:如果我们设置一个有效的默认值:

In [735]: a.default='X'
In [736]: p.parse_args([])
Out[736]: Namespace(FLAGS='X')

This behavior is part of what allows us to use such a positional in a mutually_exclusive_group .这种行为是允许我们在mutually_exclusive_group组中使用这种位置的一部分。

If you don't want to specify a valid default, then changing this to a flagged argument avoids the problem.如果您不想指定有效的默认值,则将其更改为标记参数可以避免该问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM