冲突情况下argparse中变量的推断名称是什么

Eyp*_*ros 2 python argparse python-3.x

我注意到argparse在解析器中使用一种相当"神秘"的方式来创建变量.我知道变量的名称通常很容易推断:它是长或短选项的剥离版本(没有---分别).

此外,所有连字符(-)都变为下划线(_)成为合法的变量名称.

但这让我有一个关于冲突案件的问题(我知道这是一个极端的案例,但推断的部分对我来说有点神秘).例如程序:

import argparse
parser = argparse.ArgumentParser(description="A simple test about var names")
parser.add_argument("--max-value", type=int, help="the maximum value", metavar="Maximum-value")
parser.add_argument("-m", "--max_value", action="store_true", help="Whether to the use maximum value", dest="max1")
args = parser.parse_args()
print("max_value {}".format(args.max1))
print("max-value {}".format(args.max_value))
Run Code Online (Sandbox Code Playgroud)

显然使用两个非常相似的选项(--max-value--max_value),它们导致相同的推断变量max_value.如果缺少任何一个选项,变量将max_value没有歧义.

但是当两者都存在时,显然--max_value得到了奖杯变量max_value而第二个(--max-value)获得了什么?我一直无法找到第二个变量.

那么,要访问它,我必须使用dest选项显式定义变量?如何获取可用变量名称列表?有趣的是,如果我使用dest=--max_value选项,则--max-value获取预期变量,max_value同时--max_value得到非推断变量(在我的情况下max1)!

我也知道metavar与实际变量名称无关,但仅影响帮助中的显示.

编辑:

从@Martijn Pieters回答中添加一些信息:

如果我正在写它,如果没有dest应用,则解析器遵循一般规则,该规则声明dest应用了隐式.在我的情况下也一样dest="max_value".

所以,

parser.add_argument("--max-value", type=int, help="the maximum value")
Run Code Online (Sandbox Code Playgroud)

与以下内容完全相同:

parser.add_argument("--max-value", type=int, help="the maximum value", dest="max_value")
Run Code Online (Sandbox Code Playgroud)

内部.

但是,以下代码片段应该产生不同的结果,但它不会:

# parserv1.py
import argparse
parser = argparse.ArgumentParser(description="A simple test about var names")
parser.add_argument("-m", "--max_value", action="store_true", help="Whether to the use maximum value", dest="max_value")
parser.add_argument("--max-value", type=int, help="the maximum value", metavar="Maximum-value", dest="max_value")
args = parser.parse_args()
print("max-value {}".format(args.max_value))

>>>python parserv1.py -m --max-value 3
Run Code Online (Sandbox Code Playgroud)

最大值3

# parserv2.py
import argparse
parser = argparse.ArgumentParser(description="A simple test about var names")
parser.add_argument("--max-value", type=int, help="the maximum value", metavar="Maximum-value", dest="max_value")
parser.add_argument("-m", "--max_value", action="store_true", help="Whether to the use maximum value", dest="max_value")
args = parser.parse_args()
print("max-value {}".format(args.max_value))

>>>python parserv1.py -m --max-value 3
Run Code Online (Sandbox Code Playgroud)

最大值3

两者都只是打印max_valueas 的值,与int它们声明的顺序无关.

那么,int选项的优先级高于二进制(即标志)?选项类型在这些情况下是否重要?

PS我正在使用python 3.6.3,因为它可能是版本问题,我想提一下.

Mar*_*ers 6

这里没有冲突; 两个--max-value--max_value,干脆在图书馆产生完全相同的目标名称.写入相同dest目的地名称的多个选项完全有效; 在这种情况下,命令行上使用的最后一个选项获胜:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument("--option1", dest="foo")
_StoreAction(option_strings=['--option1'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument("--option2", dest="foo")
_StoreAction(option_strings=['--option2'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--option2', 'bar', '--option1', 'baz'])
Namespace(foo='baz')
Run Code Online (Sandbox Code Playgroud)

这里--option1 baz获胜是因为--option1在命令行中最后使用了.

请注意,在命令行解析之前应用任何默认值; 第一个注册选项默认值获胜.然后解析命令行,如果只使用其中一个选项,那么与该选项关联的操作自然会获胜.

您可以选择不冲突的目的地名称.不选择容易混淆的选项字符串也是一个好主意.

如果您正在寻找关于dest给定可选参数的名称生成的正式规则集,请参阅dest选项文档:

对于可选参数操作,dest通常从选项字符串推断出值.ArgumentParser通过获取第一个长选项字符串并删除初始--字符串来生成dest的值.如果没有提供长选项字符串,dest则将通过剥离初始-字符从第一个短选项字符串派生.任何内部-字符都将转换为_字符,以确保该字符串是有效的属性名称.


所有写入相同dest目标名称的多个选项对于支持给定选项的旧的,已弃用的名称非常有用:

parser.add_argument('-n', '--new', dest='new', help="New hotness option")
# old name for the new hotness option, now deprecated but still supported
# argparse.SUPPRESS ensures it is no longer listed in the help output
parser.add_argument('-o', '--old', dest='new', help=argparse.SUPPRESS)
Run Code Online (Sandbox Code Playgroud)

因此,使用-o--old在命令行上具有与使用完全相同的效果-n--new; 在命名空间上设置相同的目标名称.