argparse默认选项基于另一个选项

时间:2013-11-18 12:40:09

标签: default argparse

假设我有一个argparse python脚本:

import argparse
parser = argparse.ArgumentParser()

parser.add_argument("--foo", required=True)

现在我想添加另一个选项--bar,它默认将“_BAR”附加到--foo参数指定的任何内容。

我的目标:

>>> parser.parse_args(['--foo', 'FOO'])
>>> Namespace(foo='FOO', bar="FOO_BAR")

>>> parser.parse_args(['--foo', 'FOO', '--bar', 'BAR'])
>>> Namespace(foo='FOO', bar="BAR")

我需要这样的东西:

parser.add_argument("--bar", default=get_optional_foo + "_BAR")

2 个答案:

答案 0 :(得分:14)

作为第一次尝试,我会使用after-argparse函数来实现这一点。

def addbar(args):
    if args.bar is None:
        args.bar = args.foo+'_BAR'

如果需要在help中反映此操作,请自行将其放在那里。

理论上,您可以为Action编写一个自定义foo,用于设置bar值的值。但这需要更加熟悉Action类。

我尝试了一个自定义Action来调整default行为的bar,但这很棘手。 parse_args在开始之前使用默认值,然后才对任何参数起作用。

答案 1 :(得分:5)

这是另一次尝试编写自定义Action类

import argparse
class FooAction(argparse.Action):
    # adapted from documentation
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values)
        defaultbar = getattr(namespace, 'bar')
        try:
            defaultbar = defaultbar%values
        except TypeError:
            # BAR has already been replaced
            pass
        setattr(namespace, 'bar', defaultbar)

parser = argparse.ArgumentParser()
parser.add_argument("--foo", required=True, action=FooAction)
parser.add_argument("--bar", default="%s_BAR")

args = parser.parse_args(['--foo', 'Foo', '--bar', 'Bar'])
# Namespace(bar='Bar', foo='Foo')
args = parser.parse_args(['--foo', 'Foo'])
# Namespace(bar='Foo_BAR', foo='Foo')
args = parser.parse_args(['--bar', 'Bar', '--foo', 'Foo'])
# Namespace(bar='Bar', foo='Foo')

请注意,该类必须知道dest参数的--bar。我还使用'%s_BAR'来轻松区分默认值和非默认值。这样可以处理--bar之前出现--foo的情况。

使这种方法复杂化的是:

  • 默认值的评估时间为add_argument
  • 默认值放在parse_args开头的命名空间中。
  • 标记(可选项)参数可以按任何顺序发生
  • Action类不是为处理交互式参数而设计的。
  • 默认情况下不会调用bar操作。
  • bar默认值可能是一个函数,但必须在parse_args之后检查是否需要进行评估。

虽然这个自定义Action可以解决这个问题,但我仍然认为我的另一个答案中的addbar函数是一个更清晰的解决方案。