次の署名を使用して引数パーサーを作成したい:
./myapp [-a [-b BVAL] | -c]
言い換えると、ユーザーは、引数を指定-b BVAL
した場合にのみ引数を指定できます-a
。
との相互に排他的なグループを作成するのは非常に簡単ですが-a
、-c
関係を作成する方法がわかりませんallow -b only if -a provided
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
Docoptは私が望んでいたようにそれを行います。素晴らしい!
docopt('./myapp [-a [-b BVAL] | -c]')
それはあなたが探しているものではありませんが、おそらくあなたが使用できるもの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')
サブパーサーを使用したくない場合は、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'")
ただし、ロジックを拡張する可能性がある場合に備えて、サブパーサーの使用を検討してください。