Python argparse:结合‘choice’、‘nargs’和‘default’时输入不一致

时间:2022-04-22 15:55:00

I have the following python program:

我有以下python程序:

#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('arg', choices=['foo', 'bar', 'baz'], default='foo', nargs='*')

args = parser.parse_args()

print(args)

If I invoke the program like this:

如果我像这样调用程序:

./prog.py

the output is

输出是

Namespace(arg='foo')

But if I invoke the program with foo as an argument:

但是如果我用foo调用程序作为参数:

./prog.py foo

the output is

输出是

Namespace(arg=['foo'])

Question

问题

How can I get arg's default value to become a list?

如何使arg的默认值变成列表?

I've tried

我试过了

I've tried setting default=['foo'] but that results in:

我试过设置default=['foo'],但结果是:

prog.py: error: argument arg: invalid choice: ['foo'] (choose from 'foo', 'bar', 'baz')

1 个解决方案

#1


5  

This is a duplicate of an old, but open, bug/issue

这是一个旧的,但开放的bug/问题的副本

http://bugs.python.org/issue9625 (argparse: Problem with defaults for variable nargs when using choices)

http://bugs.python.org/issue9625 (argparse:使用选项时变量nargs的默认问题)

A positional with * gets some special handling. Its default is always passed through the choices test if you don't provide values.

带有*的位置会得到一些特殊的处理。如果不提供值,它的默认值总是通过选择测试。

Compare that with the case of an optional

与可选的情况相比

In [138]: p=argparse.ArgumentParser()
In [139]: a=p.add_argument('--arg',choices=['foo','bar','baz'],nargs='*')

In [140]: p.parse_args([])
Out[140]: Namespace(arg=None)
In [141]: a.default=['foo']
In [142]: p.parse_args([])
Out[142]: Namespace(arg=['foo'])

The default is accepted without testing:

未经测试,默认为:

In [143]: a.default=['xxx']
In [144]: p.parse_args([])
Out[144]: Namespace(arg=['xxx'])

The relevant code is:

相关的代码是:

def _get_values(self, action, arg_strings):
    ...
    # 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)

The proposed bug/issue patch makes a small change to this block of code.

提出的bug/问题补丁对这段代码做了一个小的修改。

#1


5  

This is a duplicate of an old, but open, bug/issue

这是一个旧的,但开放的bug/问题的副本

http://bugs.python.org/issue9625 (argparse: Problem with defaults for variable nargs when using choices)

http://bugs.python.org/issue9625 (argparse:使用选项时变量nargs的默认问题)

A positional with * gets some special handling. Its default is always passed through the choices test if you don't provide values.

带有*的位置会得到一些特殊的处理。如果不提供值,它的默认值总是通过选择测试。

Compare that with the case of an optional

与可选的情况相比

In [138]: p=argparse.ArgumentParser()
In [139]: a=p.add_argument('--arg',choices=['foo','bar','baz'],nargs='*')

In [140]: p.parse_args([])
Out[140]: Namespace(arg=None)
In [141]: a.default=['foo']
In [142]: p.parse_args([])
Out[142]: Namespace(arg=['foo'])

The default is accepted without testing:

未经测试,默认为:

In [143]: a.default=['xxx']
In [144]: p.parse_args([])
Out[144]: Namespace(arg=['xxx'])

The relevant code is:

相关的代码是:

def _get_values(self, action, arg_strings):
    ...
    # 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)

The proposed bug/issue patch makes a small change to this block of code.

提出的bug/问题补丁对这段代码做了一个小的修改。