Python 2.7 argparse:如何正确嵌套可选的互斥参数?

Posted

技术标签:

【中文标题】Python 2.7 argparse:如何正确嵌套可选的互斥参数?【英文标题】:Python 2.7 argparse: How to nest optional mutally exclusive arguments properly? 【发布时间】:2013-05-23 06:54:32 【问题描述】:

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

    纯可选:[-h, --help][-v, --version] 互斥:[-f FILE, --file FILE][-u URL, --url URL] 如果选择了--url,则可选:[-V, --verbose] 如果选择了--file--url,则为必需:[-F, --format FORMAT]

所需的使用模式是:

prog.py [-h] [-v] [-f FILE (-F FORMAT) | -u URL [-V] (-F FORMAT) ]

-F 要求适用于互斥组的两个成员。 不确定是不是positional。

所以应该可以运行了:

prog.py -u "http://foo.bar" -V -F csv

如果我忘记了-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='')

因为它有一个“香草模式”可以在没有命令行参数的情况下运行,所以所有参数都必须是可选的。

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

编辑: 我尝试将-f-u 作为子解析器,如here 所述,但子命令似乎被视为位置,如果我在没有参数的情况下运行它,解析器会给我一个error: too few arguments

【问题讨论】:

你考虑过docopt吗?缺点是它允许选项值以-e.g., "-f a -F -u" (the format is "-u" here)开始 是否需要-f-u 之一?如果是这样,我正在设想一个涉及子命令或位置参数的解决方案。 @chepner:不,他们不是。我希望程序也可以在没有参数和选项的情况下运行,因此它将启动用户对话框甚至 GUI @J.F.Sebastian:docopt 看起来不错,我会深入研究并报告它是否适合我的需求 【参考方案1】:

使用 nargs=2 和元组元变量接近您的目标

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

产生:

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

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


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

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

    if positionals:
        self.error(_('too few arguments'))

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


【讨论】:

【参考方案2】:

当存在某个选项时,可以使用callback 方法在optparse 中强制执行这些点。

但是,在argparse 这些不可用。

您可以为urlfile 子选项添加subparser,并分别解析它们。 来自帮助:

注意 parse_args() 返回的对象将只包含 命令行选择的主解析器和子解析器 (而不是任何其他子解析器)。所以在上面的例子中,当 a 命令 指定时,仅存在 foo 和 bar 属性,并且当 b 命令 已指定,则仅存在 foo 和 baz 属性。

但我会正确记录用法,而忽略不适用的参数 适用。

例如让这两个命令行的行为完全相同:

prog.py -f FILE -V
prog.py -f FILE

【讨论】:

argparse 具有对具有可变数量参数的选项的内置支持,以及用于处理给定选项的参数的自定义操作。但是,我同意在这种情况下,最简单的方法是只允许-V,如果使用-f,则忽略它。 optparse 已弃用,argparse 是它的替代品。见:docs.python.org/3/library/argparse.html#upgrading-optparse-code

以上是关于Python 2.7 argparse:如何正确嵌套可选的互斥参数?的主要内容,如果未能解决你的问题,请参考以下文章

具有 nargs 行为的 Python argparse 不正确

如何将 argparse 参数传递给类

将 Python argparse.Namespace() 视为字典的正确方法是啥?

按字母顺序对 argparse 帮助进行排序

蟒蛇 2.7。解析输入参数

python中argument3是啥意思