Python argparse余数不清楚

Python argparse余数不清楚,python,arguments,argparse,Python,Arguments,Argparse,如文件所示: argparse.rements。所有剩余的命令行参数都收集到一个列表中。这对于分派到其他命令行实用程序的命令行实用程序通常很有用: 我试图将其用于完全相同的目的,但在某些情况下,它对我来说似乎有问题(或者可能我的概念错了): 结果: test.py: error: ambiguous option: -q could match -qa, -qb $ ./testcmd -qsomething test ./otherutil bar -q atr q: -qsomething

如文件所示:

argparse.rements。所有剩余的命令行参数都收集到一个列表中。这对于分派到其他命令行实用程序的命令行实用程序通常很有用:

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

结果:

test.py: error: ambiguous option: -q could match -qa, -qb
$ ./testcmd -qsomething test ./otherutil bar -q atr
q: -qsomething
extra: "test ./otherutil bar -q atr"
因此,显然,如果
otherutil
的参数与
argparse
的参数存在某种程度的“冲突”,那么它似乎无法正常工作


我希望当
argparse
到达
rements
类型的参数时,它只使用列表末尾的所有字符串,而不进行任何进一步的解析。我能以某种方式达到这种效果吗?

您需要使用两个
--

a.add_argument('--qa', nargs='?')
a.add_argument('--qb', nargs='?')
因此,您定义的选项与
-q
冲突,后者至少接受在其他地方定义的参数

编辑以回复@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)
您可以将它们称为
-abcd3-e5
-a-b-c-d3-e5
-cba-e5-d3
,…
现在,如果你有

a.add_argument('-abc',  action='store_true')
你有 argparse很难确定
-abc
是附加了3个短参数还是一个长参数。因此,您必须将参数定义为
--abc

因此,我想您不能将长参数名称与一个
-
一起使用

a.add_argument('--qa', nargs='?')
a.add_argument('--qb', nargs='?')

我知道另一种做命令行解析的方法,叫做:你可以看一下,但我怀疑它能否解决你的问题

也许是一些特殊处理的组合

这并不完美,但可能会朝着正确的方向发展:

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),)
结果:

test.py: error: ambiguous option: -q could match -qa, -qb
$ ./testcmd -qsomething test ./otherutil bar -q atr
q: -qsomething
extra: "test ./otherutil bar -q atr"
注意事项:

  • 这将在
    -q
    -q
    前缀选项的其余部分之间留出一个空格
  • 这将使用一个
    -q
    选项,但我不记得如果指定更多,它是否会引发异常(或执行任何其他有用的操作)

  • 我在尝试向底层实用程序分派选项时遇到了这个问题。我最后使用的解决方案是
    nargs='*'
    ,而不是
    nargs=argparse.rements
    ,然后只需使用“伪参数”
    --
    来分隔我的命令和底层工具的选项:

    >>> 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'])
    

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

    这更多地与缩写的处理有关,而不是与其余的
    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
    分配参数

    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
    
    在这里,歧义发生在第一遍。它试图将'-q'与两个可用选项匹配。余数的特殊动作(吸收'-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
    
    如果我加上余数动作:

    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'])
    

    如果我理解正确,argparse无法处理两个字母的“短参数”?实际上,我的目标是用argparse模拟现有命令行工具的行为,它使用诸如“-qsomething”和“-qotherthing”(其中something和otherthing不是可选参数)之类的选项。2021年支持的方法是:
    parser.add_参数(“-q”,dest=“qq”,choices=[“something”,“otherthing”)
    Old-question,但将test添加为子解析器应该可以解决这个问题。然后,它的-q将由该子解析器而不是顶级解析器处理。我也会使用--qa和--qb这对我帮助很大。在传递到argparse之前,在
    '-'
    上进行拆分非常有意义。我正要去处理海关行动等。谢谢。