如何过滤 argparse 中的 nargs 参数列表?
How to filter a list of an nargs argument in argparse?
让我们想象一下,我有一个 CLI,其中有一个名为 --list
的 nargs="*"
参数。我想过滤掉这个列表的某些元素。
例如,如果用户传入 --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
.
让我们想象一下,我有一个 CLI,其中有一个名为 --list
的 nargs="*"
参数。我想过滤掉这个列表的某些元素。
例如,如果用户传入 --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__
andformat_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
.