我想实现以下命令行参数解析方案:
我有4个参数:-g
,-wid
,-w1
和-w2
。
-w1
和-w2
始终一起出现
-wid
和(-w1 -w2)
是互斥的,但需要一个或另一个
-g
是可选的;如果未指定,则只能显示(-w1 -w2)
,但不会显示-wid
使用argparse有没有一种优雅的方法来实现它,但是没有子命令(我已经在子命令中了)?
我在想自定义动作,但是在动作的主体中,我需要知道最后一次调用它的时间(即解析最后一个参数的时候),我不知道怎么做,因为参数的数量和顺序可能会有所不同。
以下是一些更多解释:我正在编写的工具使用小部件和小工具参数-g
创建小工具。窗口小部件是现有窗口小部件 - 然后由其标识-wid
引用,或者使用参数-w1
和-w2
创建的新窗口小部件。如果未指定-g
,则该工具将使用(-w1 -w2)
创建并存储新的窗口小部件,而无需创建小工具。
提前谢谢。
答案 0 :(得分:1)
如果正确选择默认值,则可以在'parse_args'之后轻松测试'namespace'中参数值的逻辑组合。您也可以在此时发出解析器错误。有一个错误报告要求相互包容的群体。在那里,我建议添加广义组合测试的机制。但它仍然需要你自己的逻辑测试。
http://bugs.python.org/issue11588 将“必然包含”组添加到argparse
我在该问题中提出的解决方案的关键是为程序员提供seen_non_default_actions
变量。这是一个已经看到的动作列表(实际设置)(考虑到可选位置总是'看到')。我想更多地讨论如何实现包容性和排他性分组的混合。
您指定:
我有4个参数:-g,-wid,-w1和-w2。 -w1和-w2总是一起出现 -wid和(-w1 -w2)是互斥的,但是需要一个或另一个 -g是可选的;如果没有指定(-w1 -w2)可以出现,但不是-wid
我将尝试总结为:
complex_group('g', required_next_exclusive_group('wid', inclusive_group('w1','w2)))
w1
,w2
可以替换为'--w1w2',nargs=2
。一个简单的'mutual_inclusive_group'可以在这里工作。但是argparse
无法处理嵌套组。
wid
和w1w2
可以放入必需的mutually_exclusive_group
。
-g
需要if args.g is None and args.wid is None: error()
这是一个脚本,根据您的需要(我认为),使用我在Issue11588中的最新补丁。 act_w1
等是实际操作对象,可能出现在seen_actions
列表中。测试函数在subparser中注册,并在其parse_know_args()
的末尾附近执行。
parser = argparse.ArgumentParser(usage='custom usage')
sp = parser.add_subparsers(dest='cmd')
sp.required = True
spp = sp.add_parser('cmd1')
act_g = spp.add_argument('-g')
act_wid = spp.add_argument('--wid')
act_w1 = spp.add_argument('--w1')
act_w2 = spp.add_argument('--w2')
@spp.crosstest # decorator to register this function with spp
def test1(spp, seen_actions, *args):
# seen_actions - list of actions that were seen by parser
if 1==len({act_w1, act_w2}.intersection(seen_actions)):
# error if only one of these was seen
parser.error('-w1 and -w2 always appear together')
@spp.crosstest
def test2(spp, seen_actions, *args):
# required mutually exclusive wid and (w1,w2 group)
if act_wid in seen_actions:
if act_w1 in seen_actions or act_w2 in seen_actions:
parser.error('-wid and (-w1 -w2) are mutually exclusive')
elif act_w1 not in seen_actions:
parser.error('wid or (w1 and w2) required')
@spp.crosstest
def test3(spp, seen_actions, *args):
# is this the simplest logical way of expressing this?
if act_g not in seen_actions and act_wid in seen_actions:
parser.error('not g, so not wid')
args = parser.parse_args()
在此示例中,我保存并测试操作对象的存在。也可以使用dest
字符串进行测试。我正在探索使这种测试更直观和用户友好的方法。一组扩展的装饰者似乎最有希望。