简体   繁体   English

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

[英]Using argparse to get a list of unique values from choices

I have a program, for which a argument can take values from a defined list.我有一个程序,它的参数可以从定义的列表中获取值。 Every value can only be passed once.每个值只能传递一次。 At least one value must be chosen.必须至少选择一个值。 If no values are chosen, the default is that all values were chosen.如果未选择任何值,则默认为选择所有值。 The following code exhibits the desired behavior.以下代码展示了所需的行为。

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}!")

However, now I am dealing with argument validation after parsing, which seems like a anti-pattern, since argparse typically do type validation etc in the parsing step.但是,现在我正在处理解析后的参数验证,这似乎是一种反模式,因为 argparse 通常在解析步骤中进行类型验证等。

Can I get the same behavior as above from the ArgumentParser instead of making post-checks on the arguments?我可以从ArgumentParser获得与上述相同的行为,而不是对 arguments 进行后检查吗?

@chepner provided some alternatives. @chepner 提供了一些替代方案。 The one that felt most natural to me was the use of Actions.对我来说最自然的一种是使用 Actions。 Incorporating the unicity-check can be done as below:结合唯一性检查可以如下完成:

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}!")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM