[英]Argparse: how to handle variable number of arguments (nargs='*')
我认为
nargs='*'<\/code>足以处理可变数量的参数。
显然不是,我不明白这个错误的原因。
代码:
p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')
p.parse_args('1 2 --spam 8 8 9'.split())
相关的 Python 错误是Issue 15112 。
argparse: nargs='*'
如果前面有一个选项和另一个位置参数,则argparse: nargs='*'
位置参数不接受任何项目
当 argparse 解析['1', '2', '--spam', '8', '8', '9']
它首先尝试将['1','2']
与尽可能多的位置匹配尽可能的争论。 使用您的参数,模式匹配字符串是AAA*
: pos
和foo
各有 1 个参数, vars
有零个参数(记住*
表示 ZERO_OR_MORE)。
['--spam','8']
由您的--spam
参数处理。 因为vars
已经被设置为[]
,所以没有什么可以处理['8','9']
。
编程改变argparse
的情况下检查,其中0
参数字符串被满足的格局,但仍有optionals
进行解析。 然后它推迟处理该*
参数。
您可以通过首先使用parse_known_args
解析输入,然后通过对parse_args
另一个调用处理remainder
来解决parse_args
。
为了完全自由地在位置之间穿插可选项,在issue 14191 中,我建议使用parse_known_args
和optionals
,然后是只知道位置的parse_args
。 我在那里发布的parse_intermixed_args
函数可以在ArgumentParser
子类中实现,而无需修改argparse.py
代码本身。
这是一种处理子解析器的方法。 我采用了parse_known_intermixed_args
函数,为了演示的缘故对其进行了简化,然后将其parse_known_args
Parser 子类的parse_known_args
函数。 我不得不采取额外的步骤来避免递归。
最后我改变了_parser_class
解析器 Action 的 _parser_class,所以每个子解析器都使用这个替代的parse_known_args
。 另一种方法是将_SubParsersAction
子类_SubParsersAction
,可能会修改其__call__
。
from argparse import ArgumentParser
def parse_known_intermixed_args(self, args=None, namespace=None):
# self - argparse parser
# simplified from http://bugs.python.org/file30204/test_intermixed.py
parsefn = super(SubParser, self).parse_known_args # avoid recursion
positionals = self._get_positional_actions()
for action in positionals:
# deactivate positionals
action.save_nargs = action.nargs
action.nargs = 0
namespace, remaining_args = parsefn(args, namespace)
for action in positionals:
# remove the empty positional values from namespace
if hasattr(namespace, action.dest):
delattr(namespace, action.dest)
for action in positionals:
action.nargs = action.save_nargs
# parse positionals
namespace, extras = parsefn(remaining_args, namespace)
return namespace, extras
class SubParser(ArgumentParser):
parse_known_args = parse_known_intermixed_args
parser = ArgumentParser()
parser.add_argument('foo')
sp = parser.add_subparsers(dest='cmd')
sp._parser_class = SubParser # use different parser class for subparsers
spp1 = sp.add_parser('cmd1')
spp1.add_argument('-x')
spp1.add_argument('bar')
spp1.add_argument('vars',nargs='*')
print parser.parse_args('foo cmd1 bar -x one 8 9'.split())
# Namespace(bar='bar', cmd='cmd1', foo='foo', vars=['8', '9'], x='one')
对于不知道什么是nargs
:
nargs
代表Number Of Arguments
3
: 3 个值,可以是您想要的任何数字?
: 单个值,可以是可选的*
: 一个灵活数量的值,将被收集到一个列表中+
: 类似 *,但至少需要一个值argparse.REMAINDER
:命令行中剩余的所有值示例:
蟒蛇
import argparse
my_parser = argparse.ArgumentParser()
my_parser.add_argument('--input', action='store', type=int, nargs=3)
args = my_parser.parse_args()
print(args.input)
控制台
$ python nargs_example.py --input 42
usage: nargs_example.py [-h] [--input INPUT INPUT INPUT]
nargs_example.py: error: argument --input: expected 3 arguments
$ python nargs_example.py --input 42 42 42
[42, 42, 42]
简单的解决方案:在指定pos
和foo
之前指定--spam
标志:
p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')
p.parse_args('--spam 8 1 2 8 9'.split())
如果在指定变量参数后放置--spam
标志,则同样有效。
p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')
p.parse_args('1 2 8 9 --spam 8'.split())
编辑:对于它的价值,似乎将*
更改为+
也将修复错误。
p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='+')
p.parse_args('1 2 --spam 8 8 9'.split())
如果您希望至少有一个可选参数,那么p.add_argument('vars', nargs='+')<\/code>将适用于您的具体情况
"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.