python - 带有方括号的 metavar 的 argparse AssertionError

标签 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

工作日:

ζ 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

最佳答案

这看起来是 argparse 中的一个错误,与您如何使用 metavar 变量有关。这里有一些有用的信息来追踪这个……

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

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

第三,这是在 assert 语句中引发的 AssertionError。我们可以使用 -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 中的一个低优先级错误。还有它may already be reported正如@CharlesDuffy 在评论中指出的那样。

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

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}' 并且效果很好...

关于python - 带有方括号的 metavar 的 argparse AssertionError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41105229/

相关文章:

python - argparse 中子解析器之后的可选参数

python - Pandas 数据框默认使用 .loc

Python argparse 正则表达式

Python argparse 参数 : issue with passing strings containing hyphens

python - 如何基于列合并 Pandas 数据框?

python - 如何在Python的argparse中相互排除多个参数

Python argparse : type inconsistencies when combining 'choices' , 'nargs' 和 'default'

python - 如何将 "x=y"字符串的元组解析为 python 中的字典?

python - DLL 加载失败 : The specific module could not be found (VSCode, Numpy)

python - 在 Django 中提交表单后重定向到带参数的主页