我想实现以下命令行参数解析方案:

我有4个参数:-g-wid-w1-w2
-w1-w2总是一起出现
-wid(-w1 -w2)是互斥的,但一个或另一个是必需的
-g是可选的;如果未指定,则只能显示(-w1 -w2),但不能显示-wid
有没有一种使用argparse而不使用子命令(我已经在子命令中)来实现此目标的优雅方法?

我当时在考虑自定义操作,但是在操作主体中,我需要知道上次调用该操作的时间(即,最后一个参数何时被解析),自该操作以来,我不知道该怎么做数字和参数的顺序可能会有所不同。

以防万一:我正在编写的工具会使用小部件和小工具参数-g创建一个小工具。该窗口小部件可以是现有的窗口小部件,然后通过其id -wid进行引用,或者是使用参数-w1-w2创建的新窗口小部件。如果未指定-g,则该工具将仅使用(-w1 -w2)创建并存储新的小部件,而无需创建小工具。

先感谢您。

最佳答案

如果正确选择默认值,则可以轻松地测试“parse_args”之后“ namespace ”中参数值的逻辑组合。您还可以在那时发出解析器错误。有一个错误报告要求相互包含的组。在那里,我建议了一种添加广义组合测试的机制。但是它仍然需要您自己的逻辑测试。

http://bugs.python.org/issue11588
在argparse中添加“必要包含”组

我在该问题中提出的解决方案的关键是使seen_non_default_actions变量可供程序员使用。这是已看到的 Action 的列表(实际上是一组)(考虑到可选位置始终是“可见的”)。我希望看到更多有关如何实现包容性和排他性分组混合的讨论。

您指定:



我将其总结为:

complex_group('g', required_next_exclusive_group('wid', inclusive_group('w1','w2)))
w1w2可以替换为'--w1w2',nargs=2。一个简单的“mutually_inclusive_group”将在这里工作。但是argparse无法处理嵌套组。

可以将widw1w2放入所需的mutually_exclusive_group中。
-g需要像if args.g is None and args.wid is None: error()这样的测试

这是一个脚本,该脚本使用您在Issue11588中发布的最新补丁按您的要求运行(我认为)。 act_w1等是实际的操作对象,它们可能会出现在seen_actions列表中。测试功能已注册到子解析器,并在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()

在此示例中,我保存并测试了 Action 对象的存在。也可以使用dest字符串进行测试。我正在探索使测试更加直观和用户友好的方法。一组扩展的装饰器似乎最有前途。

关于Python argparse : Complex Argument Parsing Scenario,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22929087/

10-12 21:09