argparse AssertionError,metavar有方括号

时间:2016-12-12 16:27:01

标签: python argparse

下面是一些示例代码,它显示了一个有趣的案例,其中三个独立工作的代码行在一起运行时不起作用,但如果您将标志名称字符串更改为更简单的类似" -a",则可以正常工作" -b"等,或者如果你注释掉任何一个单独的标志。测试脚本的用法包含在测试脚本的外部解析器中,该解析器启动各种内部实验解析器。解析器a,b和c都是相同的,但每个都有一个标记。这些解析器的帮助都有效。破解的解析器也与其他解析器相同,所有标志现在都处于活动状态(未注释)。

我真的不知道为什么会出现这种情况,因为标志应该是彼此独立的对象,并且有自己的内存分配和一切,所以启用一个选项不应该打破其他选项。奇怪的是,如果您只是使用' [lin] | log'更改标志名称或位的随机位,这也会修复它。这用解析器d来说明。

我会将此报告为错误,但我不知道哪个部分实际上已损坏,我的代码或argparse。失败时的错误对于识别这一点并不是很有帮助,但我怀疑argparse有问题。

from __future__ import print_function
import argparse
from pdb import set_trace as br
mainparser=argparse.ArgumentParser(description='select whether to work or fail')
mainparser.add_argument('p',action='store',type=str,metavar='[working_a|working_b|working_c|working_d|broken]', help='Type "working_a" or "working_b" or "working_c" or "working_d" or "broken" to see the parser succeed or fail')

working_parser_a=argparse.ArgumentParser(description='a')
# working_parser_a.add_argument('-cmap',metavar='hot_desaturated',nargs=1,default='hot_desaturated',help='Colormap to use for colorbar')
working_parser_a.add_argument('-cbar_scale',metavar='[lin]|log',nargs=1,type=str,default='lin',help='Linear or log scale colormap')
working_parser_a.add_argument('-title',metavar='The Plot Title',type=str,nargs=1,help='Define the plot title that goes above the plot')

working_parser_b=argparse.ArgumentParser(description='b')
working_parser_b.add_argument('-cmap',metavar='hot_desaturated',nargs=1,default='hot_desaturated',help='Colormap to use for colorbar')
# working_parser_b.add_argument('-cbar_scale',metavar='[lin]|log',nargs=1,type=str,default='lin',help='Linear or log scale colormap')
working_parser_b.add_argument('-title',metavar='The Plot Title',type=str,nargs=1,help='Define the plot title that goes above the plot')

working_parser_c=argparse.ArgumentParser(description='c')
working_parser_c.add_argument('-cmap',metavar='hot_desaturated',nargs=1,default='hot_desaturated',help='Colormap to use for colorbar')
working_parser_c.add_argument('-cbar_scale',metavar='[lin]|log',nargs=1,type=str,default='lin',help='Linear or log scale colormap')
# working_parser_c.add_argument('-title',metavar='The Plot Title',type=str,nargs=1,help='Define the plot title that goes above the plot')

broken_parser=argparse.ArgumentParser(description='e')
broken_parser.add_argument('-cmap',metavar='hot_desaturated',help='')
broken_parser.add_argument('-cbar_scale',metavar='[lin]|log',default='lin',help='')
broken_parser.add_argument('-title',metavar='The Plot Title',help='')

working_parser_d=argparse.ArgumentParser(description='d')
working_parser_d.add_argument('-a',metavar='hot_desaturated',nargs=1,default='hot_desaturated',help='Colormap to use for colorbar')
working_parser_d.add_argument('-b',metavar='[lin]|log',nargs=1,type=str,default='lin',help='Linear or log scale colormap')
working_parser_d.add_argument('-c',metavar='The Plot Title',type=str,nargs=1,help='Define the plot title that goes above the plot')

args=mainparser.parse_args()
if args.p=='working_a':
    working_parser_a.parse_args(['-h'])
elif args.p=='working_b':
    working_parser_b.parse_args(['-h'])
elif args.p=='working_c':
    working_parser_c.parse_args(['-h'])
elif args.p=='working_d':
    working_parser_d.parse_args(['-h'])
elif args.p=='broken':
    broken_parser.parse_args(['-h'])
else:
    p=args.p
    print("The argument "+p+" is not a valid parser",file=sys.stderr)
    mainparser.parse_args(['-h'])

输出: 工作解析器a:

ζ python test.py working_a
usage: test.py [-h] [-cbar_scale [lin]|log] [-title The Plot Title]

a

optional arguments:
  -h, --help            show this help message and exit
  -cbar_scale [lin]|log
                         Linear or log scale colormap
  -title The Plot Title
                         Define the plot title that goes above the plot

工作解析器b:

ζ python test.py working_b
usage: test.py [-h] [-cmap hot_desaturated] [-title The Plot Title]

b

optional arguments:
  -h, --help            show this help message and exit
  -cmap hot_desaturated
                        Colormap to use for colorbar
  -title The Plot Title
                        Define the plot title that goes above the plot

工作解析器c:

ζ python test.py working_c
usage: test.py [-h] [-cmap hot_desaturated] [-cbar_scale [lin]|log]

c

optional arguments:
  -h, --help            show this help message and exit
  -cmap hot_desaturated
                        Colormap to use for colorbar
  -cbar_scale [lin]|log
                        Linear or log scale colormap

工作d:

ζ python test.py working_d
usage: test.py [-h] [-a hot_desaturated] [-b [lin]|log] [-c The Plot Title]

d

optional arguments:
  -h, --help          show this help message and exit
  -a hot_desaturated  Colormap to use for colorbar
  -b [lin]|log        Linear or log scale colormap
  -c The Plot Title   Define the plot title that goes above the plot

断裂:

ζ python test.py broken
Traceback (most recent call last):
  File "test.py", line 42, in <module>
    broken_parser.parse_args(['-h'])
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 1703, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 1735, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 1941, in _parse_known_args
    start_index = consume_optional(start_index)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 1881, in consume_optional
    take_action(action, args, option_string)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 1809, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 1015, in __call__
    parser.print_help()
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 2328, in print_help
    self._print_message(self.format_help(), file)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 2302, in format_help
    return formatter.format_help()
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 300, in format_help
    help = self._root_section.format_help()
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 230, in format_help
    func(*args)
  File "/usr/local/lib/python2.7/site-packages/argparse.py", line 351, in _format_usage
    assert ' '.join(opt_parts) == opt_usage
AssertionError

1 个答案:

答案 0 :(得分:1)

这看起来是argparse中与您使用metavar变量的方式相关的错误。这是一些有用的信息,可用于跟踪此信息......

首先,当您的metavar中包含'['']'字符时,似乎就会发生这种情况。

其次,它似乎取决于参数的数量(超过2个触发问题)。参数的实际数字可能是一个读取鲱鱼 - 它可能与格式化程序是否需要将参数拆分为多行或与参数数量松散耦合的其他内容有关...

第三,这是在AssertionError声明中提出的assert。我们可以使用-O运行代码,看看会发生什么:

$ python3 -O ~/sandbox/ap.py broken
usage: ap.py [-h] [-cmap hot_desaturated] [-title The Plot Title]
             [-cbar_scale [lin] |log]
<snip>

我们可以在最后一行看到我们的[lin]|log已被拆分为[lin] |log,这可能是断言失败的原因。

所以,我想说这可能是argparse中的低优先级错误。正如@CharlesDuffy在评论中指出的那样may already be reported

请注意,最好使用choices=...来验证参数的输入。当你这样做时,argparse将为你创建一个适合你的metavar:

broken_parser.add_argument('-cbar_scale',default='lin', type=str, nargs=1, help='', choices=('lin', 'log'))

结果:

usage: ap.py [-h] [-cmap hot_desaturated] [-title The Plot Title]
             [-cbar_scale {lin,log}]

这不是完全好(例如,它没有告诉你默认值是什么),但你可以轻松地将它放在help字符串中。如果确实有必要,可以使用大括号的大括号:metavar='{{lin}|log}',这样就可以了......