argparse (python) 是否支持互斥的参数组?
如果我有参数 '-a', '-b', '-c', '-d'
以及 add_mutually_exclusive_group()
函数,我的程序将必须只使用其中之一。有没有办法将其结合起来,以便程序只接受 '-a 999 -b 999'
或 '-c 999 -d 999'
?
编辑:添加一个简单的程序以提高清晰度:
>>> parser = argparse.ArgumentParser()
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('-a')
>>> group.add_argument('-b')
>>> group.add_argument('-c')
>>> group.add_argument('-d')
然后仅 ./app.py -a | ./app.py -b | ./app.py -c |可以调用./app.py -d
。是否可以将 argparse 分组为排除组,以便只有 ./app.py -a .. -b .. | ./app.py -c .. -d ..
被调用吗?
If I have the arguments '-a', '-b', '-c', '-d'
, with the add_mutually_exclusive_group()
function my program will have to use just one of them. Is there a way to combine that, so that the program will accept only either '-a 999 -b 999'
or '-c 999 -d 999'
?
Edit: adding a simple program for more clarity:
>>> parser = argparse.ArgumentParser()
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('-a')
>>> group.add_argument('-b')
>>> group.add_argument('-c')
>>> group.add_argument('-d')
Then only ./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d
can be called. Is it possible to have argparse group the exclusion groups, so that only ./app.py -a .. -b .. | ./app.py -c .. -d ..
be called?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
子解析器?
与unhammer的答案类似,但具有更多的用户控制权。注意:我还没有实际测试过这个方法,但它在理论上应该可以工作并且具有 python 的功能。
您可以创建两个解析器,每个解析器对应两个组,并使用条件来执行互斥部分。本质上仅使用 argparse 进行部分参数解析。使用这种方法,您也可以超越 unhammer 答案的限制。
Subparsers?
Similar to unhammer's answer, but with more user control. Note: I have not actually tested this method, but it should work in theory and with the capabilities of python.
You can create two parsers, one for each of the two groups, and use conditionals to do the mutually exclusive part. Essentially using argparse for only part of the argument parsing. Using this method, you can go beyond the limitations of unhammer's answer as well.
编辑:没关系。因为 argparse 做出了一个可怕的选择,即在调用 group.add_argument 时必须创建一个选项。那不会是我的设计选择。如果您非常需要此功能,可以尝试使用 ConflictsOptionParser 来实现:
因此,当我们调用它,我们可以看到我们得到了想要的效果。
警告消息不会告知您
'-a'
和'-b'
与'-c'
不兼容,但是可以制作更合适的错误消息。下面是较旧的错误答案。旧编辑: [此编辑是错误的,但如果
argparse
以此方式工作,这不是一个完美的世界吗?] 我之前的回答实际上是不正确的,您应该能够通过为每个互斥选项指定一组来使用 argparse 来完成此操作。我们甚至可以使用 itertools 来概括该过程。这样我们就不必显式地输入所有组合:EDIT: Never mind. Because
argparse
makes the horrible choice of having to create an option when invokinggroup.add_argument
. That wouldn't be my design choice. If you're desperate for this feature, you can try doing it with ConflictsOptionParser:Thus when we invoke it, we can see we get the desired effect.
The warning message doesn't inform you that both
'-a'
and'-b'
are incompatible with'-c'
, however a more appropriate error message could be crafted. Older, wrong answer below.OLDER EDIT: [This edit is wrong, although wouldn't it be just a perfect world if
argparse
worked this way?] My previous answer actually was incorrect, you should be able to do this withargparse
by specifying one group per mutually exclusive options. We can even useitertools
to generalize the process. And make it so we don't have to type out all the combinations explicitly:@hpaulj 评论中引用的 argparse 增强请求在九年多后仍然开放,因此我认为其他人可能会从我刚刚发现的解决方法中受益。根据增强请求中的此评论,我发现我能够向两个添加一个选项使用此语法的不同互斥组:
这对于我的目的来说已经足够好了:
当然,访问 argparse 的私有成员相当脆弱,所以我可能不会在生产代码中使用这种方法。另外,精明的读者可能会注意到使用消息具有误导性,因为它意味着
-o
和-i
可以一起使用,但它们不能一起使用(!)但是,我我仅使用此脚本进行测试,因此我并不过分担心。 (我认为,“真正”修复使用消息将需要更多的时间来完成这项任务,但如果您知道对此的巧妙技巧,请发表评论。)The
argparse
enhancement request referenced in @hpaulj's comment is still open after more than nine years, so I figured other people might benefit from the workaround I just discovered. Based on this comment in the enhancement request, I found I was able to add an option to two different mutually-exclusive groups using this syntax:This works well enough for my purposes:
Accessing private members of
argparse
is, of course, rather brittle, so I probably wouldn't use this approach in production code. Also, an astute reader may notice that the usage message is misleading, since it implies that-o
and-i
can be used together when they cannot(!) However, I'm using this script for testing only, so I'm not overly concerned. (Fixing the usage message 'for real' would, I think, require much more time than I can spare for this task, but please comment if you know a clever hack for this.)我自己偶然发现了这个问题。从我对 argparse 文档的阅读来看,似乎没有一种简单的方法可以在 argparse 中实现这一目标。我考虑过使用 parse_known_args,但这很快就相当于编写 argparse 的专用版本;-)
也许需要一份错误报告。同时,如果你愿意让你的用户做一点额外的输入,你可以用子组来伪造它(比如 git 和 svn 的参数如何工作),例如,
不理想,但至少它给你带来了 argparse 的好处没有太多丑陋的黑客行为。我最终取消了开关,只使用带有所需子参数的子解析器操作。
Just stumbled on this problem myself. From my reading of the argparse docs, there doesn't seem to be a simple way to achieve that within argparse. I considered using parse_known_args, but that soon amounts to writing a special-purpose version of argparse ;-)
Perhaps a bug report is in order. In the meanwhile, if you're willing to make your user do a tiny bit extra typing, you can fake it with subgroups (like how git and svn's arguments work), e.g.
Not ideal, but at least it gives you the good from argparse without too much ugly hackery. I ended up doing away with the switches and just using the subparser operations with required subarguments.