【问题标题】:is it possible to denote some set of argparse's arguments without using subparsers?是否可以在不使用子解析器的情况下表示一组 argparse 的参数?
【发布时间】:2017-02-23 16:13:52
【问题描述】:

我有一个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,但它们似乎只是用于帮助文本。

谢谢!

【问题讨论】:

  • 我不清楚您要做什么。你的意思是-p1-p2 只能与-input2 的/作为子结构/“子选项”一起出现?
  • 参数组主要用于互斥选项。你们团体的性质是什么?例如。你能在 dest 前面加上前缀来帮助分组参数吗?
  • 你如何为dest添加前缀? @9000
  • @jwodder,不,所有参数都是独立的,可以任意组合指定。但由于某些参数是“参数”,我希望能够通过调用 params = vars(args.params) 将它们作为一个组
  • @AlexLenail:我的想法是parser.add_argument('-p1', ... dest='output_p1')等。然后你可以自己通过.strartswith('output_')对解析结果进行分组,如果你愿意,可以去掉前缀。

标签: python argparse


【解决方案1】:

这听起来像是一个变体 - 我如何接受任意的“键=值”对?多年来,人们以各种方式提出了这个问题,并给出了各种答案。

最近的一篇:

Parsing "python foo.py -DVAR1=9 -DVAR2=Off" with argparse

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

Using variable arg names with argparse - 在将sys.argv 传递给解析器之前对其进行处理。

python argparse store --foo=bar as args.key='foo', args.value='bar'

建议自定义 Action 类。

我认为我们还建议了一个自定义 Namespace 类。

用于分组值的内置机制是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'}

【讨论】:

  • 你能做得更好吗?重新阅读我的问题——这又变得相关了——我觉得这个功能应该由 python 提供。我对 python 的治理了解不多,但我很想贡献这个。在我看来,这将建立在 argument groups 的基础上,它已经存在,但仅用于帮助文本......
  • 欢迎您在http://bugs.python.org/ 上搜索argparse 问题。研究其中的一些,包括开放式和封闭式,看看做出改变涉及什么。有两个挑战 1) 证明这是一个紧迫且普遍的问题,以及 2) 编写完整的补丁(包含测试和文档)。
猜你喜欢
  • 2015-10-09
  • 2020-05-16
  • 2014-10-25
  • 2011-03-18
  • 2015-11-08
  • 1970-01-01
  • 2019-05-21
  • 2015-10-30
  • 1970-01-01
相关资源
最近更新 更多