4

次の署名を使用して引数パーサーを作成したい:

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

言い換えると、ユーザーは、引数を指定-b BVALした場合にのみ引数を指定できます-a

との相互に排他的なグループを作成するのは非常に簡単ですが-a-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

それはあなたが探しているものではありませんが、おそらくあなたが使用できるもの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 に答える
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 に答える