4

(在python 3.6.0上运行)

TL;博士

Usage: prog.py {caesar | vigenere} [key]

parser = argparse.ArgumentParser()
subp = parser.add_subparsers()
caesar = subp.add_parser("caesar", aliases=["c"], allow_abbrev=True)
args = parser.parse_args()
$ python prog.py caes 123
prog.py: error: invalid choice: 'caes' (choose from 'caesar', 'c')

为什么subparser即使使用 ,缩写也无效allow_abbrev=True


长版

argparse基本上,在接受缩写subparsers名称/别名时遇到问题。

这是代码:

Usage: prog.py [caesar] [key]

import sys, argparse

def main(argv):
parser = argparse.ArgumentParser
         (description="runs text through X cipher")
subp = parser.add_subparsers\
         (help="sub-command help")

#<ArgumentParser object>
caesar = subp.add_parser\
         ("caesar", aliases=["c"], allow_abbrev=True)
caesar.add_argument\
         ("key", metavar = "key (any integer)",\
          type = int, default = 0)


args = parser.parse_args()
print(caesar)

if __name__ == "__main__":
sys.argv = list(str(c).lower() for c in sys.argv[0:])
main(sys.argv)

因此,从上面的代码中,应该预期应该接受以下任何内容:

- "Caesar" or "caesar"
- "C" or "c" 
- Any abbreviation in between "c" and "caesar" 

所以问题来了:

这有效:$ python prog.py c 123O

这给出了一个错误:$ python prog.py caes 123X

prog.py: error: invalid choice: 'cae' (choose from 'caesar', 'c')

现在这是令人困惑的部分。

根据argparse 文档

ArgumentParser 支持使用 add_subparsers() 方法创建此类子命令。add_subparsers() 方法通常不带参数调用,并返回一个特殊的操作对象。这个对象有一个方法add_parser(),它接受一个命令名称和任何 ArgumentParser 构造函数参数,并返回一个可以像往常一样修改的 ArgumentParser 对象。

  1. 好的,所以任何人object created with add_subparser()都可以创建自己ArgumentParser objectobject.add_parser()权利吗?

  2. ...这意味着这个新创建的ArgumentParser对象应该能够接受任何ArgumentParser参数是吗?

ArgumentParser定义:

class 
argparse.ArgumentParser(
prog=None, usage=None, 
description=None, epilog=None, 
parents=[],formatter_class=argparse.HelpFormatter, 
prefix_chars='-',fromfile_prefix_chars=None, 
argument_default=None,conflict_handler='error', 
add_help=True, allow_abbrev=True)

创建一个新的ArgumentParser对象。所有参数都应作为关键字参数传递。每个参数在下面都有自己更详细的描述,但简而言之,它们是:

allow_abbrev- 如果缩写明确,则允许缩写长选项。

(默认:

在 3.5 版更改:添加了 allow_abbrev 参数。

(这是在 python 3.6.0 上)


提前谢谢各位

4

2 回答 2

3

实现了一个允许子解析器名称缩写的补丁,但是当它被证明有问题时被撤回:

问题 12713:允许用户缩写子命令

允许用户关闭长选项的缩写是一个不同的问题,在

问题 14910:argparse:禁用缩写

代码的两个不同部分。

allow_abbrev -如果缩写明确,则允许缩写长选项。

使用以下命令创建长选项:

caesar.add_argument('-f','--foobar')

使用默认allow_abbrev值,这将适用于“-f”、“--foo”和“--foobar”。在long_option这种情况下是'--foobar'。有了它False,'--foo' 将不起作用。

它主要parser决定是否c是有效caesarcae子解析器命令(通过subp,由创建的特殊操作对象parser.add_subparsers)。这更像是一个带有 的位置choices

parser.add_argument('foo', choices = ['c', 'caesar'])
于 2017-11-10T17:44:34.943 回答
0

我得到的错误是:

usage: [-h] {caesar,c} ...
: error: unrecognized arguments: a e s

暗示缩写应该是可组合的,因为两个不同的缩写“c”和“a”可以通过传递来引用ca

那里真的应该发生什么?ca既是 thec和(不存在的)a缩写形式的组合,也是缩写。解析器应该更喜欢哪个?因此,在设计库时必须明确解决这个问题:为了可预测性,你不能同时拥有两者。

话虽如此,也许您可​​以通过传递来调整结果conflict_handler='resolve'https://docs.python.org/3/library/argparse.html#allow-abbrev

于 2017-11-10T15:40:21.657 回答