Python argparse:组合 'choices'、'nargs' 和 'default' 时类型不一致
Python argparse: type inconsistencies when combining 'choices', 'nargs' and 'default'
我有以下 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)
如果我这样调用程序:
./prog.py
输出是
Namespace(arg='foo')
但是如果我用 foo
作为参数调用程序:
./prog.py foo
输出是
Namespace(arg=['foo'])
问题
如何让arg
的默认值变成list
?
我试过了
我试过设置 default=['foo']
但结果是:
prog.py: error: argument arg: invalid choice: ['foo'] (choose from 'foo', 'bar', 'baz')
这是旧的但开放的副本,bug/issue
http://bugs.python.org/issue9625 (argparse: Problem with defaults for variable nargs when using choices
)
带有 *
的 positional
得到一些特殊处理。如果您不提供值,它的默认值总是通过 choices
测试。
将其与 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'])
未经测试默认接受:
In [143]: a.default=['xxx']
In [144]: p.parse_args([])
Out[144]: Namespace(arg=['xxx'])
相关代码为:
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)
建议的 bug/issue 补丁对此代码块进行了小幅更改。
我在 typed_argparse
库中针对该限制创建了一个小的解决方法。在您的示例中,解决方案如下所示:
import argparse
from typed_argparse import Choices
parser = argparse.ArgumentParser()
parser.add_argument(
"arg",
choices=Choices("foo", "bar", "baz"), # Wrap the choices in Choices
default=["foo"], # Use any list like default
nargs="*",
)
Choices
的实现非常简单,如果您喜欢copy/pasteable。
我有以下 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)
如果我这样调用程序:
./prog.py
输出是
Namespace(arg='foo')
但是如果我用 foo
作为参数调用程序:
./prog.py foo
输出是
Namespace(arg=['foo'])
问题
如何让arg
的默认值变成list
?
我试过了
我试过设置 default=['foo']
但结果是:
prog.py: error: argument arg: invalid choice: ['foo'] (choose from 'foo', 'bar', 'baz')
这是旧的但开放的副本,bug/issue
http://bugs.python.org/issue9625 (argparse: Problem with defaults for variable nargs when using choices
)
带有 *
的 positional
得到一些特殊处理。如果您不提供值,它的默认值总是通过 choices
测试。
将其与 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'])
未经测试默认接受:
In [143]: a.default=['xxx']
In [144]: p.parse_args([])
Out[144]: Namespace(arg=['xxx'])
相关代码为:
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)
建议的 bug/issue 补丁对此代码块进行了小幅更改。
我在 typed_argparse
库中针对该限制创建了一个小的解决方法。在您的示例中,解决方案如下所示:
import argparse
from typed_argparse import Choices
parser = argparse.ArgumentParser()
parser.add_argument(
"arg",
choices=Choices("foo", "bar", "baz"), # Wrap the choices in Choices
default=["foo"], # Use any list like default
nargs="*",
)
Choices
的实现非常简单,如果您喜欢copy/pasteable。