如何过滤 argparse 中的 nargs 参数列表?

How to filter a list of an nargs argument in argparse?

让我们想象一下,我有一个 CLI,其中有一个名为 --listnargs="*" 参数。我想过滤掉这个列表的某些元素。

例如,如果用户传入 --list foo bar foo baz 我想过滤掉所有 values == "foo" 以便最终列表变为 ["bar", "baz"]:

parser = argparse.ArgumentParser()
parser.add_argument(
    "--list",
    nargs="*",
)
parser.parse_args(["--list", "foo", "bar", "foo", "baz"])

我显然可以在生成的参数的 post 处理步骤中解决这个问题。但是我想知道 argparse 中是否有一个 内置机制 允许在没有 post-post 处理的情况下实现这样的过滤器。

我尝试使用 type=lambda: ... 但它似乎只在值本身而不是最终列表上被调用,所以我不能用它来过滤我想的值?

argparse.add_argument 有一个参数 action。来自文档:

ArgumentParser objects associate command-line arguments with actions. These actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by parse_args().

因此我们可以使用 action 进行过滤。文档指出:

The recommended way to create a custom action is to extend Action, overriding the __call__ method and optionally the __init__ and format_usage methods.

过滤 argparse.Action 可能如下所示:

import argparse
from typing import Optional, Callable


class FilterNargsAction(argparse.Action):
    def __init__(
        self,
        option_strings,
        dest,
        nargs: Optional[str] = None,
        condition: Optional[Callable] = None,
        **kwargs
    ):
        if nargs not in ("*", "+"):
            # We could also allow integers 
            raise ValueError("nargs must be one of (*, +)")
        if condition is None:
            raise ValueError("condition needs to be set")
        self.condition = condition
        super().__init__(option_strings, dest, nargs=nargs, **kwargs)

    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, [v for v in values if self.condition(v)])


parser = argparse.ArgumentParser()
parser.add_argument(
    "--list",
    nargs="*",
    action=FilterNargsAction,
    condition=lambda x: x != "foo",
)
args = parser.parse_args(["--list", "foo", "bar", "foo", "baz"])

print(args.list)

如果在解析时绝对需要过滤参数,可以使用自定义 action.