使用 argparse 从选项中获取唯一值列表

Using argparse to get a list of unique values from choices

我有一个程序,它的参数可以从定义的列表中获取值。每个值只能传递一次。必须至少选择一个值。如果未选择任何值,则默认为选择所有值。以下代码展示了所需的行为。

import argparse

############################# Argument parsing
all_targets = ["bar", "baz", "buzz"]
p = argparse.ArgumentParser()
p.add_argument(
    "--targets", default=all_targets, choices=all_targets, nargs="+",
)
args = p.parse_args()
targets = args.targets
if len(targets) > len(set(targets)):
    raise ValueError("You may only foo every target once!")

############################## Actual program
for target in targets:
    print(f"You just foo'ed the {target}!")

但是,现在我正在处理解析后的参数验证,这似乎是一种反模式,因为 argparse 通常在解析步骤中进行类型验证等。

我可以从 ArgumentParser 得到与上面相同的行为而不是对参数进行 post 检查吗?

@chepner 提供了一些替代方案。对我来说最自然的一种是 Actions 的使用。结合单性检查可以按如下方式完成:

import argparse


class CheckUniqueStore(argparse.Action):
    """Checks that the list of arguments contains no duplicates, then stores"""

    def __call__(self, parser, namespace, values, option_string=None):
        if len(values) > len(set(values)):
            raise argparse.ArgumentError(
                self,
                "You cannot specify the same value multiple times. "
                + f"You provided {values}",
            )
        setattr(namespace, self.dest, values)


############################# Argument parsing
all_targets = ["bar", "baz", "buzz"]
p = argparse.ArgumentParser()
p.add_argument(
    "--targets",
    default=all_targets,
    choices=all_targets,
    nargs="+",
    action=CheckUniqueStore,
)
args = p.parse_args()

############################## Actual program
for target in args.targets:
    print(f"You just foo'ed a {target}!")