如何在argparse中筛选nargs参数的列表



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

例如,如果用户输入了--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"])

很明显,我可以在生成的args的后处理步骤中解决这个问题。然而,我想知道argparse中是否有一个内置机制,可以在不进行后期处理的情况下实现这样的过滤器。

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

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

ArgumentParser对象将命令行参数与操作相关联。尽管大多数操作只是向parse_args((返回的对象添加一个属性,但这些操作可以通过与之相关的命令行参数执行任何操作。

所以我们可以用action进行过滤。文件说明:

创建自定义操作的推荐方法是扩展Action,覆盖__call__方法以及可选的__init__format_usage方法。

过滤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

相关内容

  • 没有找到相关文章

最新更新