【问题标题】:Python argparse: "multiple multiples" of arguments?Python argparse:参数的“倍数”?
【发布时间】:2017-05-05 05:30:02
【问题描述】:

我想使用 argparse 在命令行上接收任意数量的 sets 位置参数。例如:

myapp.py show 1

show 参数是一个“操作”,1 是一个“操作数”。

我希望能够接受多个组操作和操作数:

myapp.py show 1 test 2 write 3

我知道我可以添加一个带有Nnargs 参数的参数作为最后一个参数,以允许该参数的任意重复次数。我希望做同样的事情,但每次重复不止一个参数。

在这个例子中:

myapp.py show 1 test

应该是无效的,因为每个操作都必须带有一个操作数。

另外,假设所有操作数都是整数,所有运算符都是字符串:

myapp.py 1 show 2 test

应该失败,或者至少可以在代码中检测到,这样我才能导致失败,因为操作员必须先来。

在不同的项目中,每个重复的参数集我可能还需要两个以上的“参数”,例如:

myapp.py test 1 outputFile.dat write 2 writeFile.dat

这个可以吗?

【问题讨论】:

  • 如果在这些操作数前面加上--,您感觉如何? myapp.py --show 1 --test 2
  • 我可以这样做,但它不适用于每个操作需要两个操作数的第二个示例。
  • click怎么样?
  • @fdmillion -- 抱歉,我说的是操作数,是指操作符。如果给定运算符有 2 个操作数,为什么它不起作用? myapp.py --show 1 --test 1 2 --other 1。只要每个运算符都知道它需要多少个操作数......另外,您是否希望运算符被多次给出?他们的顺序重要吗?
  • 这不适合argparse。只需将sys.argv[1:] 拆分为所需的配对或三胞胎组合即可。

标签: python argparse


【解决方案1】:

扩展@mgilson 给出的 cmets 中的建议,这是一个操作以 -- 为前缀的示例,这似乎可行:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs=2)
...
>>> parser.add_argument('--bar', nargs=2)
...
>>> args = parser.parse_args(('--foo', '1', 'out.dat', '--bar', '2', 'out.dat'))
>>> args
Namespace(bar=['2', 'out.dat'], foo=['1', 'out.dat'])

然后您可以使用另一个 argparser 对每个子元素进行额外的解析:

>>> fooparser = argparse.ArgumentParser()
>>> fooparser.add_argument('num', type=int)
...
>>> fooparser.add_argument('fname')
...
>>> fooparser.parse_args(args.foo)
Namespace(fname='out.dat', num=1)

当然,如果第二个 argparser 失败,您会收到一条非常奇怪的错误消息,因此您可能需要自己手动解析每个 2-arg 并生成自己的错误消息。

【讨论】:

    【解决方案2】:
    argv=sys.argv[1:]
    adict = {k:int(v) for k,v in zip(argv[::2], argv[1::2])}
    

    In words - 从字典中的命令行收集成对的字符串。这也适用于来自nargs='*' 位置的未区分列表字符串或来自parse_known_argsextras。错误检查/捕获留给读者作为练习。


    In [41]: argv='myapp.py show 1 test 2 write 3'.split()
    In [42]: argv=argv[1:]
    In [43]: adict = {k:int(v) for k,v in zip(argv[::2], argv[1::2])}
    In [44]: adict
    Out[44]: {'show': 1, 'test': 2, 'write': 3}
    

    或者生成器方法可以让您更好地控制拆分和解析:

    def gen(alist):
        it = iter(alist)
        while True:
            yield (next(it),int(next(it)))
    In [68]: {k:v for k,v in gen(argv)}
    Out[68]: {'show': 1, 'test': 2, 'write': 3}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      • 2018-07-09
      • 2014-07-23
      • 2013-03-31
      • 2015-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多