argparse.REMAINDER 改变位置参数的行为 [英] argparse.REMAINDER changes the behavior of positional arguments

查看:63
本文介绍了argparse.REMAINDER 改变位置参数的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果没有argparse.REMAINDER,可选参数可以在位置参数之前或之后:

导入 argparse解析器 = argparse.ArgumentParser()parser.add_argument('-a')parser.add_argument('b')print(parser.parse_args('-a 1 2'.split())) # Namespace(a='1', b='2')print(parser.parse_args('2 -a 1'.split())) # Namespace(a='1', b='2')

但是对于argparse.REMAINDER,可选参数必须在前面:

parser.add_argument('c', nargs=argparse.REMAINDER)print(parser.parse_args('-a 1 2 3'.split())) # Namespace(a='1', b='2', c=['3'])print(parser.parse_args('2 -a 1 3'.split())) # 命名空间(a=None, b='2', c=['-a', '1', '3'])

如何在使用 argparse.REMAINDER 时正确解析最后一行?

解决方案

为了补充 kabanus 的答案,了解一些关于如何解析参数的知识可能会有所帮助.

它遍历参数,首先寻找位置,然后是可选,然后是位置,...,

在位置步骤,它尝试尽可能多地匹配,使用 nargs 作为主要因素.默认是一个字符串(你的'b');'*' 将匹配下一个可选(-a);但 REMAINDER 忽略该约束并匹配到最后.因此,位置"评估是贪婪的,而带有 REMAINDER 的评估尤其贪婪.

所以在'2 -a 1 3'的情况下,开头的'2'可以匹配'b',其余的可以匹配'c'.只需一个 'positionals' 评估就消耗了整个列表,包括 '-a',然后就完成了.

文档示例显示了这一点:

<预><代码>>>>打印(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))命名空间(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')

'--foo' 被视为可选的,但 '--arg1' 是 REMAINDER 的一部分.'args' 在 'command' 之后立即填充.

如果您想保留对何时使用 REMAINDER 的控制,请将其设为可选,add_argument('-c',nargs='...').否则,您将受此位置/可选循环的支配.

顺便说一下,子解析器是用 narg=argarse.PARSER 实现的,它是+..."的名字.它类似于 REMAINDER,但至少需要一个字符串(子解析器名称).它也会消耗其路径上的所有内容.

您可能想要使用*"和--"来触发消耗其他所有东西"操作,而不是 REMAINDER.

Without argparse.REMAINDER, optional arguments can be in front of or after positional arguments:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-a')
parser.add_argument('b')

print(parser.parse_args('-a 1 2'.split()))  # Namespace(a='1', b='2')
print(parser.parse_args('2 -a 1'.split()))  # Namespace(a='1', b='2')

But with argparse.REMAINDER, optional arguments must be in front:

parser.add_argument('c', nargs=argparse.REMAINDER)

print(parser.parse_args('-a 1 2 3'.split()))  # Namespace(a='1', b='2', c=['3'])
print(parser.parse_args('2 -a 1 3'.split()))  # Namespace(a=None, b='2', c=['-a', '1', '3'])

How can I parse the last line correctly, while argparse.REMAINDER is used?

解决方案

To add to kabanus's answer, it may help to know a bit about how arguments are parsed.

It iterates over the arguments, first looking for positionals, then optionals, then positionals, ...,

At the positionals step it tries to match as many as it can, using the nargs as a primary factor. The default is one string (your 'b'); '*' will match up to the next optional (the -a); but a REMAINDER ignores that constraint and matches to the end. So a 'positionals' evaluation is greedy, and one with REMAINDER is especially greedy.

So in the '2 -a 1 3' case, the initial '2' can match 'b', and the rest can match 'c'. Just one 'positionals' evaluation consumes the whole list, including the '-a', and it is done.

The documentation example shows this:

>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')

The '--foo' is handled as optional, but the '--arg1' is part of the REMAINDER. 'args' is filled immediately after 'command'.

If you want to retain control over when the REMAINDER is used, make it an optional, add_argument('-c',nargs='...'). Otherwise you are at the mercy of this positionals/optionals loop.

By the way, subparsers are implemented with a narg=argarse.PARSER, which is the name for '+...'. It's like REMAINDER but requires at least one string (the subparser name). It too consumes everything in its path.

Instead of REMAINDER you might want to use '*' and use '--' to trigger the 'consume everything else' action.

这篇关于argparse.REMAINDER 改变位置参数的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆