正如文件所示:
argparse.REMAINDER。所有剩余的命令行参数都收集到一个列表中。这对于调度到其他命令行实用程序的命令行实用程序通常很有用:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print parser.parse_args('--foo B cmd --arg1 XX ZZ'.split())
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')
我试图将它用于完全相同的目的,但在某些情况下,我似乎错误(或者我的概念错了):
import argparse
a = argparse.ArgumentParser()
a.add_argument('-qa', nargs='?')
a.add_argument('-qb', nargs='?')
a.add_argument('rest', nargs=argparse.REMAINDER)
a.parse_args('-qa test ./otherutil bar -q atr'.split())
结果:
test.py: error: ambiguous option: -q could match -qa, -qb
显然,如果otherutil
有这样的论据以某种方式与argparse
的论据“碰撞”,那么它似乎无法正常工作。
我希望当argparse
到达REMAINDER
类型的参数时,它只会耗尽列表末尾的所有字符串,而无需进一步解析。我能以某种方式达到这种效果吗?
答案 0 :(得分:2)
您需要使用两个--
。
a.add_argument('--qa', nargs='?')
a.add_argument('--qb', nargs='?')
因此,您定义的选项与-q
冲突,至少接受一个参数,在其他地方定义
ArgumentParser.add_argument(name or flags...)
name or flags - Either a name or a list of option strings, e.g. foo or -f, --foo.
编辑回复@PDani第一条评论:
This post很有意思。
据我所知,argparse遵循POSIX和GNU风格。
重要的是短(1个字母)选项可以组合在一起,如果一个选项需要一个参数,这可以附加到选项字母。例如,如果你有这样的东西
a.add_argument('-a', action='store_true')
a.add_argument('-b', action='store_true')
a.add_argument('-c', action='store_true')
a.add_argument('-d', nargs=1)
a.add_argument('-e', nargs=1)
您可以将其称为-abcd3 -e5
或-a -b -c -d3 -e5
或-cba -e5 -d3
,...
现在,如果你有
a.add_argument('-abc', action='store_true')
你有
argparse很难决定-abc
是附加3个短参数还是一个长参数。因此,您不得不将参数定义为--abc
。
所以我猜你不能将长参数名称与-
一起使用。
我知道另一种方法来执行名为docopt的命令行解析:你可以看看,但我怀疑它可以解决你的问题。
答案 1 :(得分:1)
也许是ArgumentParser.parse_known_args()
和其他一些特殊处理的组合?
这不是完美的,但可能会朝着正确的方向发展:
import argparse
import sys
a = argparse.ArgumentParser()
# treat the common-prefixed arguments as options to the prefix
a.add_argument("-q")
# allow a delimiter to set off your arguments from those which should go to the
# other utility, and use parse_known_args() if the delimiter is not present
argv = sys.argv[1:]
if "--" in argv:
i = argv.index("--")
args, extra = a.parse_args(argv[:i]), argv[i + 1:]
else:
a.add_argument("extra", nargs=argparse.REMAINDER)
args, _ = a.parse_known_args(argv)
extra = args.extra
# complain if the `-q` option was not specified correctly
if args.q not in ("something", "otherthing"):
a.error("Must specify '-qsomething' or '-qotherthing'")
print "q:", "-q%s" % (args.q,)
print "extra:", '"%s"' % (" ".join(extra),)
结果:
$ ./testcmd -qsomething test ./otherutil bar -q atr
q: -qsomething
extra: "test ./otherutil bar -q atr"
注意事项:
-q
与-q
其余部分之间的空格 - 前缀选项。-q
选项,但我不记得是否会引发异常(或做任何其他有用的事情),如果指定了更多。答案 2 :(得分:1)
在尝试向基础实用程序分发选项时遇到了这个问题。我最终使用的解决方案是nargs='*'
而不是nargs=argparse.REMAINDER
,然后只使用“伪参数” --
来分隔命令和基础工具的选项:
>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--myflag', action='store_true')
>>> parser.add_argument('toolopts', nargs='*')
>>> parser.parse_args('--myflag -- -a --help'.split())
Namespace(myflag=True, toolopts=['-a', '--help'])
这在帮助输出中非常容易记录。
答案 3 :(得分:0)
这与缩写的处理有关,而不是与其余nargs
有关。
In [111]: import argparse
In [112]: a = argparse.ArgumentParser()
...:
...: a.add_argument('-qa', nargs='?')
...: a.add_argument('-qb', nargs='?')
In [113]: a.parse_args('-qa test ./otherutil bar -q atr'.split())
usage: ipython3 [-h] [-qa [QA]] [-qb [QB]]
ipython3: error: ambiguous option: -q could match -qa, -qb
argparse
进行2遍解析。首先,它尝试将字符串分类为选项(标志)或参数。其次,它在解析位置和可选内容之间交替,根据nargs
分配参数。
这里,模棱两可出现在第一遍。它正在尝试将'-q'与两个可用的可选项进行匹配。 REMAINDER的特殊操作(吸收'-q'就像是普通字符串一样)直到第二遍才发生。
较新的argparse
版本允许我们关闭缩写处理:
In [114]: a.allow_abbrev
Out[114]: True
In [115]: a.allow_abbrev=False
In [116]: a.parse_args('-qa test ./otherutil bar -q atr'.split())
usage: ipython3 [-h] [-qa [QA]] [-qb [QB]]
ipython3: error: unrecognized arguments: ./otherutil bar -q atr
如果我添加了REMAINDER动作:
In [117]: a.add_argument('rest', nargs=argparse.REMAINDER)
In [118]: a.parse_args('-qa test ./otherutil bar -q atr'.split())
Out[118]: Namespace(qa='test', qb=None, rest=['./otherutil', 'bar', '-q', 'atr'])
如@Colin所建议的那样使用'-'是有效的,因为该字符串可在第一遍中被识别:
In [119]: a.allow_abbrev=True
In [120]: Out[117].nargs='*'
In [121]: a.parse_args('-qa test -- ./otherutil bar -q atr'.split())
Out[121]: Namespace(qa='test', qb=None, rest=['./otherutil', 'bar', '-q', 'atr'])