我要实现的是:
--read_file <some file>
和positional argument
只能指定其中一个。
prog --read_file inputfile
可以。
prog --read_file
也可以。
prog input1 input2 ...
可以。
prog input1 --read_file
不好。
所以我这样做了:
readlist_group.add_argument(
"--read_file",
dest="read_file",
metavar="file_to_read",
help="If enabled, input will be ignored and list will be read from given file. [default: %(default)s][const: %(const)s]",
type=argparse.FileType("r"),
default=None,
const=sys.stdin,
nargs="?",
)
readlist_group.add_argument(
dest="inputs",
help="inputs",
metavar="input",
type=str,
nargs="*",
)
但是,我得到了ValueError: mutually exclusive arguments must be optional
,但是“ *”是可选的吗?
答案 0 :(得分:1)
除非提供默认值,否则“ *”为“必需”。
In [15]: parser=argparse.ArgumentParser()
In [16]: gp = parser.add_mutually_exclusive_group()
In [17]: a = gp.add_argument('-r', nargs='?', default='def', const='con')
In [18]: b = gp.add_argument('foo', nargs='*', default=[])
In [19]: parser.print_help()
usage: ipython3 [-h] [-r [R] | foo [foo ...]]
positional arguments:
foo
optional arguments:
-h, --help show this help message and exit
-r [R]
我应该查看代码和/或文档以了解原因。
In [22]: parser.parse_args([])
Out[22]: Namespace(foo=[], r='def')
In [23]: parser.parse_args(['-r'])
Out[23]: Namespace(foo=[], r='con')
In [24]: parser.parse_args(['-r','test'])
Out[24]: Namespace(foo=[], r='test')
In [25]: parser.parse_args(['test'])
Out[25]: Namespace(foo=['test'], r='def')
In [26]: parser.parse_args(['test','1','2'])
Out[26]: Namespace(foo=['test', '1', '2'], r='def')
In [27]: parser.parse_args(['test','1','2','-r'])
usage: ipython3 [-h] [-r [R] | foo [foo ...]]
ipython3: error: argument -r: not allowed with argument foo
In [28]: parser.parse_args(['-r','a','b'])
usage: ipython3 [-h] [-r [R] | foo [foo ...]]
ipython3: error: argument foo: not allowed with argument -r
确定,在代码中:
def _get_positional_kwargs(self, dest, **kwargs):
# make sure required is not specified
if 'required' in kwargs:
msg = _("'required' is an invalid argument for positionals")
raise TypeError(msg)
# 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
# return the keyword arguments with no option strings
return dict(kwargs, dest=dest, option_strings=[])
在bug /问题中可能已经讨论了为什么要这样编码,但是我不记得任何细节了。
几年前,这使我感到困惑:
https://bugs.python.org/issue26235(需要记录)
How can I create an argparse mutually exclusive group with multiple positional parameters?