Python argparse REMAINDER 不清楚

PDa*_*ani 7 python arguments argparse

正如文档所暗示的那样:

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')
Run Code Online (Sandbox Code Playgroud)

我试图将其用于完全相同的目的,但在某些情况下对我来说似乎有问题(或者我的概念可能错误)

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())
Run Code Online (Sandbox Code Playgroud)

结果:

test.py: error: ambiguous option: -q could match -qa, -qb
Run Code Online (Sandbox Code Playgroud)

很明显,如果otherutil有这样的参数与给定的参数“冲突” argparse,它似乎不能正常工作。

我希望当argparse达到REMAINDER那种参数时,它只会用完列表末尾的所有字符串,而无需进一步解析。我能以某种方式达到这种效果吗?

Col*_*lau 7

我在尝试将选项分派给基础实用程序时遇到了这个问题。我最终使用的解决方案是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'])
Run Code Online (Sandbox Code Playgroud)

这相当容易记录在帮助输出中。


hpa*_*ulj 7

这更多地与缩写的处理有关,而不是与 REMAINDER 有关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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果我添加 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'])
Run Code Online (Sandbox Code Playgroud)

正如 @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'])
Run Code Online (Sandbox Code Playgroud)


Fra*_*ano 4

您需要使用两个 --.

a.add_argument('--qa', nargs='?')
a.add_argument('--qb', nargs='?')
Run Code Online (Sandbox Code Playgroud)

因此,您定义的选项与 a 发生冲突-q,该选项至少接受一个在其他地方定义的参数

来自argparse 文档

ArgumentParser.add_argument(name or flags...)

name or flags - Either a name or a list of option strings, e.g. foo or -f, --foo.
Run Code Online (Sandbox Code Playgroud)

编辑回复@PDani第一条评论:

这篇文章很有趣。

据我了解,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)
Run Code Online (Sandbox Code Playgroud)

你可以称它们为-abcd3 -e5or-a -b -c -d3 -e5-cba -e5 -d3, ...
现在,如果你有

a.add_argument('-abc',  action='store_true')
Run Code Online (Sandbox Code Playgroud)

并且 argparse 很难决定-abc附加的是 3 个短参数还是 1 个长参数。所以你被迫将参数定义为--abc

所以我猜你不能将长参数名称与 one 一起使用-

我知道有一种名为docopt的命令行解析替代方法:您可以看一下,但我怀疑它能否解决您的问题。