下面是一些示例代码,展示了一个有趣的案例,其中三个独立工作的代码行在一起运行时不起作用,但如果将标志名称字符串更改为更简单的名称(如“-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/