4

我想创建具有以下签名的参数解析器:

./myapp [-a [-b BVAL] | -c]

换句话说,用户-b BVAL只有在他提供了参数的情况下才能提供参数-a

-a创建and的互斥组很容易-c,但我不知道如何创建关系allow -b only if -a provided

4

4 回答 4

4

您可以从 ArgumentParser 继承以添加一些自定义功能。在这里,我提出了一个例外,但您可以修改它以实现您想要的任何内容。只需更改on_dependency_error()方法以满足您的需求。

from argparse import ArgumentParser

class FancyParser(ArgumentParser):
    # {'b': 'a'} Where b depends on a
    dependencies = {}

    def on_dependency_error(self, arg, depends_on):
        raise FancyParser.DependencyError(
                    'Argument %s depends on %s' % (arg, depends_on))

    def add_argument(self, *args, **kwargs):
        depends_on = kwargs.get('depends_on')
        if depends_on:
            self.dependencies[kwargs.get('dest') or args[0]] = depends_on
            del kwargs['depends_on']
        return super(FancyParser, self).add_argument(*args, **kwargs)

    def parse_args(self, *args, **kwargs):
        args = super(FancyParser, self).parse_args(*args, **kwargs)
        for arg, depends_on in self.dependencies.iteritems():
            if getattr(args, arg) and not getattr(args, depends_on):
                self.on_dependency_error(arg, depends_on)
        return args

    class DependencyError(Exception):
        def __init__(self, *args, **kwargs):
            return super(FancyParser.DependencyError,
                         self).__init__(*args, **kwargs)

然后你可以像这样使用它 -

args = ['-a', '-b', 'BVAL', '-c']
parser = FancyParser()
parser.add_argument('-a', dest='a', action='store_true')
parser.add_argument('-b', dest='b', depends_on='a')
parser.add_argument('-c', dest='c', action='store_true')
try:
    parser.parse_args(args)
except FancyParser.DependencyError as e:
    # Whatever here...
    pass
于 2012-12-24T03:15:29.650 回答
3

Docopt完全按照我的意愿去做。了不起!

docopt('./myapp [-a [-b BVAL] | -c]')
于 2013-05-08T14:38:53.340 回答
2

如果您不想使用子解析器,您可以使用 parser.error 自己处理您的参数值。

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-a', dest='a', default='')  # you can use other defaults surely
parser.add_argument('-b', dest='b', default='')
parser.add_argument('-c', dest='c', default='')

args = parser.parse_args()

if args.b and not args.a:
    parser.error("Option 'b' can't be specified without 'a'")

但仍然考虑使用子解析器,以防您可能扩展逻辑

于 2012-12-21T10:06:44.853 回答
2

这不完全是您正在寻找的东西,但也许您可以使用add_subparsers()doc)?

执行以下操作:

import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='sub-command help')
a = subparsers.add_parser('a')
c = subparsers.add_parser('c')
a.add_argument('b')
于 2012-12-09T16:23:55.137 回答