是否可以在不使用子解析器的情况下表示一些 argparse 的参数?

is it possible to denote some set of argparse's arguments without using subparsers?

我有一个 argparser,有两个参数子集,输入和参数。我的命令看起来像

program -input1 <input1> -input2 <input2> -p1 <param1> -p2 <param2>

我愿意

args = parser.parse_args()
params = vars(args.params)

而不是

params = {"p1": args.p1, "p2": args.p2, etc...}

是否有一种优雅的方式来做类似的事情:

parser.add_argument("-p1", dest='p1', part_of=params)

Subparsers 看起来不像是为此而生的。或者他们是?

Argparse 有 argument groups,但它们似乎只是用于帮助文本。

谢谢!

这听起来像是 - 我如何接受任意 'key=value' 对?多年来,人们以各种方式提出这个问题,得到了各种答案。

最近的一个:

我的解决方案是将 -DVAR1=9 拆分为 ('VAR1',9) 并将其附加到 D 属性。使用自定义 type.

- 这会在将 sys.argv 传递给解析器之前对其进行处理。

建议自定义 Action class。

我想我们还建议了自定义 Namespace class。

用于对值进行分组的内置机制是 nargsappend 操作。您可以一起获得列表列表的属性。

JSON字符串也可以用来输入复杂的数据结构


class MyAction(argparse._StoreAction):
    def __call__(self, parser, namespace, values, option_string=None):
        print('storing', option_string)
        arg = getattr(namespace, self.dest)
        if arg is None:
            arg = {}
        arg[option_string] = values
        setattr(namespace, self.dest, arg)

In [135]: p=argparse.ArgumentParser()
In [136]: p.add_argument('--p1',action=MyAction,dest='p');
In [137]: p.add_argument('--p2',action=MyAction,dest='p');
In [138]: p.parse_args('--p1 one --p2 two'.split())
storing --p1
storing --p2
Out[138]: Namespace(p={'--p2': 'two', '--p1': 'one'})
In [139]: _.p
Out[139]: {'--p1': 'one', '--p2': 'two'}

显然,这可以通过多种方式进行改进 - 将键修剪为 'p1' 甚至“1”、保存到列表、嵌套命名空间或其他自定义结构等。

此方法仍然需要您为每个“--pn”变体定义一个 add_argument

另一种方法是保持 argparse 简单,生成如下命名空间:

In [141]: argparse.Namespace(p1='one', p2='two', input1=1, input2=3)
Out[141]: Namespace(input1=1, input2=3, p1='one', p2='two')

然后自己分组。

In [142]: args=argparse.Namespace(p1='one', p2='two', input1=1, input2=3)
In [143]: {key:getattr(args,key) for key in ['p1','p2']}
Out[143]: {'p1': 'one', 'p2': 'two'}