繁体   English   中英

"argparse:如何处理可变数量的参数(nargs='*')"

[英]Argparse: how to handle variable number of arguments (nargs='*')

我认为nargs='*'<\/code>足以处理可变数量的参数。 显然不是,我不明白这个错误的原因。

代码:

p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')

p.parse_args('1 2 --spam 8 8 9'.split())

相关的 Python 错误是Issue 15112

argparse: nargs='*'如果前面有一个选项和另一个位置参数,则argparse: nargs='*'位置参数不接受任何项目

当 argparse 解析['1', '2', '--spam', '8', '8', '9']它首先尝试将['1','2']与尽可能多的位置匹配尽可能的争论。 使用您的参数,模式匹配字符串是AAA*posfoo各有 1 个参数, vars有零个参数(记住*表示 ZERO_OR_MORE)。

['--spam','8']由您的--spam参数处理。 因为vars已经被设置为[] ,所以没有什么可以处理['8','9']

编程改变argparse的情况下检查,其中0参数字符串被满足的格局,但仍有optionals进行解析。 然后它推迟处理该*参数。

您可以通过首先使用parse_known_args解析输入,然后通过对parse_args另一个调用处理remainder来解决parse_args

为了完全自由地在位置之间穿插可选项,在issue 14191 中,我建议使用parse_known_argsoptionals ,然后是只知道位置的parse_args 我在那里发布的parse_intermixed_args函数可以在ArgumentParser子类中实现,而无需修改argparse.py代码本身。


这是一种处理子解析器的方法。 我采用了parse_known_intermixed_args函数,为了演示的缘故对其进行了简化,然后将其parse_known_args Parser 子类的parse_known_args函数。 我不得不采取额外的步骤来避免递归。

最后我改变了_parser_class解析器 Action 的 _parser_class,所以每个子解析器都使用这个替代的parse_known_args 另一种方法是将_SubParsersAction子类_SubParsersAction ,可能会修改其__call__

from argparse import ArgumentParser

def parse_known_intermixed_args(self, args=None, namespace=None):
    # self - argparse parser
    # simplified from http://bugs.python.org/file30204/test_intermixed.py
    parsefn = super(SubParser, self).parse_known_args # avoid recursion

    positionals = self._get_positional_actions()
    for action in positionals:
        # deactivate positionals
        action.save_nargs = action.nargs
        action.nargs = 0

    namespace, remaining_args = parsefn(args, namespace)
    for action in positionals:
        # remove the empty positional values from namespace
        if hasattr(namespace, action.dest):
            delattr(namespace, action.dest)
    for action in positionals:
        action.nargs = action.save_nargs
    # parse positionals
    namespace, extras = parsefn(remaining_args, namespace)
    return namespace, extras

class SubParser(ArgumentParser):
    parse_known_args = parse_known_intermixed_args

parser = ArgumentParser()
parser.add_argument('foo')
sp = parser.add_subparsers(dest='cmd')
sp._parser_class = SubParser # use different parser class for subparsers
spp1 = sp.add_parser('cmd1')
spp1.add_argument('-x')
spp1.add_argument('bar')
spp1.add_argument('vars',nargs='*')

print parser.parse_args('foo cmd1 bar -x one 8 9'.split())
# Namespace(bar='bar', cmd='cmd1', foo='foo', vars=['8', '9'], x='one')

对于不知道什么是nargs

nargs代表Number Of Arguments

  • 3 : 3 个值,可以是您想要的任何数字
  • ? : 单个值,可以是可选的
  • * : 一个灵活数量的值,将被收集到一个列表中
  • + : 类似 *,但至少需要一个值
  • argparse.REMAINDER :命令行中剩余的所有值

示例:

蟒蛇

import argparse

my_parser = argparse.ArgumentParser()
my_parser.add_argument('--input', action='store', type=int, nargs=3)

args = my_parser.parse_args()

print(args.input)

控制台

$ python nargs_example.py --input 42
usage: nargs_example.py [-h] [--input INPUT INPUT INPUT]
nargs_example.py: error: argument --input: expected 3 arguments

$ python nargs_example.py --input 42 42 42
[42, 42, 42]

查看更多

简单的解决方案:在指定posfoo之前指定--spam标志:

p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')

p.parse_args('--spam 8 1 2 8 9'.split())

如果在指定变量参数后放置--spam标志,则同样有效。

p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')

p.parse_args('1 2 8 9 --spam 8'.split())

编辑:对于它的价值,似乎将*更改为+也将修复错误。

p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='+')

p.parse_args('1 2 --spam 8 8 9'.split())

如果您希望至少有一个可选参数,那么p.add_argument('vars', nargs='+')<\/code>将适用于您的具体情况

"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM