这种参数间依赖更容易实现after解析。
args = parser.parse_args()
if not namespace.git_user and namespace.clone:
parser.error('"--clone" requires legal git user')
那时,双方git_user
and clone
已被解析,并具有最终值。
当您实现它时,自定义操作仅在存在时运行--gituser
争论。所以我认为当你给出它时它会引发错误--gituser
没有--clone
.
你可以给--clone
类似的自定义操作,但它还必须处理store_true
细节。以及应该发生什么--clone --gituser value
顺序?这clone
操作将在之前运行gituser
值已被解析。像这样的测试会遇到一些棘手的论证顺序问题。
其他几个问题:
单元测试文件,test/test_argparse.py
有一个带有这样的相互测试的自定义操作的示例。但这只是一个玩具,验证这样的代码是否被允许。
=================
理论上,您可以实施--clone
设定的动作required
的属性--gituser
行动。这样一来,如果--gituser
没有使用,最终required
动作测试parse_args
会引发错误。但这需要保存对显示在中的操作的引用out[95]
(或者发现在parse._actions
列表。可行但混乱。
===================
下面是一对交互的自定义操作类的示例test/test_argparse.py
.
class OptionalAction(argparse.Action):
def __call__(self, parser, namespace, value, option_string=None):
try:
# check destination and option string
assert self.dest == 'spam', 'dest: %s' % self.dest
assert option_string == '-s', 'flag: %s' % option_string
# when option is before argument, badger=2, and when
# option is after argument, badger=<whatever was set>
expected_ns = NS(spam=0.25)
if value in [0.125, 0.625]:
expected_ns.badger = 2
elif value in [2.0]:
expected_ns.badger = 84
else:
raise AssertionError('value: %s' % value)
assert expected_ns == namespace, ('expected %s, got %s' %
(expected_ns, namespace))
except AssertionError:
e = sys.exc_info()[1]
raise ArgumentParserError('opt_action failed: %s' % e)
setattr(namespace, 'spam', value)
NS
是一个简写argparse.Namespace
.
class PositionalAction(argparse.Action):
def __call__(self, parser, namespace, value, option_string=None):
try:
assert option_string is None, ('option_string: %s' %
option_string)
# check destination
assert self.dest == 'badger', 'dest: %s' % self.dest
# when argument is before option, spam=0.25, and when
# option is after argument, spam=<whatever was set>
expected_ns = NS(badger=2)
if value in [42, 84]:
expected_ns.spam = 0.25
elif value in [1]:
expected_ns.spam = 0.625
elif value in [2]:
expected_ns.spam = 0.125
else:
raise AssertionError('value: %s' % value)
assert expected_ns == namespace, ('expected %s, got %s' %
(expected_ns, namespace))
except AssertionError:
e = sys.exc_info()[1]
raise ArgumentParserError('arg_action failed: %s' % e)
setattr(namespace, 'badger', value)
它们用于
parser = argparse.ArgumentParser()
parser.add_argument('-s', dest='spam', action=OptionalAction,
type=float, default=0.25)
parser.add_argument('badger', action=PositionalAction,
type=int, nargs='?', default=2)
并应该与:
'-s0.125' producing: NS(spam=0.125, badger=2)),
'42', NS(spam=0.25, badger=42)),
'-s 0.625 1', NS(spam=0.625, badger=1)),
'84 -s2', NS(spam=2.0, badger=84)),
这是可以进行交叉检查的示例。但我要重申的是,通常交互最好在解析之后处理,而不是在解析期间处理。
至于实施问题 - 如果用户不给你--gituser
,您的自定义操作永远不会被调用。这Action.__call__
of an optional
仅当使用该参数时才使用。positionals
总是被使用,但不是optionals
.