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
这些不可用。
您可以为url
和file
子选项添加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 不正确