我想用以下签名创建参数解析器:
./myapp [-a [-b BVAL] | -c]
换句话说,用户只有在提供参数-b BVAL
的情况下才能提供参数-a
。
创建互斥的-a
和-c
组非常容易,但我无法弄清楚如何创建关系allow -b only if -a provided
答案 0 :(得分:5)
您可以从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
答案 1 :(得分:4)
Docopt就像我想要的那样做。了不起!
docopt('./myapp [-a [-b BVAL] | -c]')
答案 2 :(得分: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')
答案 3 :(得分:2)
如果您不想使用subparsers,可以使用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'")
但是仍然考虑使用subparsers,以防你扩展逻辑