Python 2.7 argparse:如何正确嵌套可选的mutally独占参数?

ryp*_*pel 12 python command-line-arguments python-2.7 argparse

我的程序应包括以下选项,由argparse正确解析:

  1. 纯粹是可选的:[-h, --help][-v, --version]
  2. 相互排斥:[-f FILE, --file FILE][-u URL, --url URL]
  3. 选择是否--url可选:[-V, --verbose]
  4. 如果选择--file或被--url选中,则需要:[-F, --format FORMAT]

所需的使用模式是:

prog.py [-h] [-v] [-f FILE (-F FORMAT) | -u URL [-V] (-F FORMAT) ]
Run Code Online (Sandbox Code Playgroud)

-F施加到互斥组的成员的要求.
不确定它是否是一个位置.

所以应该可以运行:

prog.py -u "http://foo.bar" -V -F csv
Run Code Online (Sandbox Code Playgroud)

如果我忘记了-F(就像他应该的那样),解析器会尖叫.

到目前为止我做了什么:

parser = ArgumentParser(decription='foo')

group = parser.add_mutually_exclusive_group()    
group.add_argument('-f','--file', nargs=1, type=str, help='')
group.add_argument('-u','--url', nargs=1, type=str, help='')    

parser.add_argument('-V','--verbose', action='store_true', default=False, help='')
parser.add_argument('-F','--format', nargs=1, type=str, help='')
Run Code Online (Sandbox Code Playgroud)

由于它具有在没有命令行参数的情况下运行的"vanilla模式",因此所有参数都必须是可选的.

如何在我的代码中实现第3点和第4点?

编辑:
我尝试-f-u作为subparsers,如这里所述,但子命令似乎被视为位置和解析器给我一个error: too few arguments如果我没有参数运行它.

hpa*_*ulj 5

使用nargs = 2和元组metavar近似于你的目标

parser = argparse.ArgumentParser(prog='PROG')
group = parser.add_mutually_exclusive_group()
group.add_argument('-f','--file', nargs=2, metavar=('FILE','FORMAT'))
group.add_argument('-u','--url', nargs=2, metavar=('URL','FORMAT'))
parser.add_argument('-V','--verbose', action='store_true',help='optional with url')
Run Code Online (Sandbox Code Playgroud)

产生:

usage: PROG [-h] [-f FILE FORMAT | -u URL FORMAT] [-V]

optional arguments:
  -h, --help            show this help message and exit
  -f FILE FORMAT, --file FILE FORMAT
  -u URL FORMAT, --url URL FORMAT
  -V, --verbose         optional with url
Run Code Online (Sandbox Code Playgroud)

这需要格式以及文件名或URL,它只是不需要-F.正如其他人所指出的那样-V可以忽略-f.


我尝试使用-f和-u作为subparsers,如此处所述,但是子命令似乎被视为位置,并且解析器给我一个错误:如果我在没有参数的情况下运行它,则参数太少.

在最新版本中,子命令不再被视为必需的位置.据我所知,这是更改错误消息的副作用,以提供更多信息.而不是_parse_known_args做:

    if positionals:
        self.error(_('too few arguments'))
Run Code Online (Sandbox Code Playgroud)

它会扫描_actions以查看哪些是必需的,然后在错误消息中按名称列出它们.这在http://bugs.python.org/issue9253中讨论.我知道这个变化正在开发中(3.4),也可能在3.3中.