我刚开始使用argparse模块。我写了以下简化代码片段来演示我遇到的问题。
from argparse import ArgumentParser
if __name__ == '__main__':
parser = ArgumentParser('Test argparse. This string needs to be relatively long to trigger the issue.')
parser.add_argument('-f', '--fin', help='a', required = True)
parser.add_argument('-o', '--out ', help='b', required = True)
parser.add_argument('-t', '--trans', help='c', required = True)
args = parser.parse_args()
print(repr(vars(args)))
使用参数 -h 运行脚本时将生成 AssertionError
Traceback (most recent call last):
File "arg.py", line 10, in <module>
args = parser.parse_args()
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 1707, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 1739, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 1945, in _parse_known_args
start_index = consume_optional(start_index)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 1885, in consume_optional
take_action(action, args, option_string)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 1813, in take_action
action(self, namespace, argument_values, option_string)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 1017, in __call__
parser.print_help()
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 2341, in print_help
self._print_message(self.format_help(), file)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 2325, in format_help
return formatter.format_help()
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 278, in format_help
help = self._root_section.format_help()
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 208, in format_help
func(*args)
File "C:\Users\user\AppData\Local\Continuum\Anaconda\envs\py3k\lib\argparse.py", line 329, in _format_usage
assert ' '.join(opt_parts) == opt_usage
AssertionError
减少传递给 ArgumentParser 的描述字符串的长度使其正常工作。 删除其中一个参数也会有所帮助。
我在这里做错了吗?我的环境是:
Python 3.3.5 | Anaconda 1.9.2(64位)| (默认,2014年3月10日, 11:25:04)[MSC v.1600 64位(AMD64)]在win32上
答案 0 :(得分:11)
代码中的--out
后面有一个额外的空格。变化:
parser.add_argument('-o', '--out ', help='b', required = True)
为:
parser.add_argument('-o', '--out', help='b', required = True)
问题的根本原因是Python中的assert
检查
只有当Python试图将帮助文本分解为时才会出现的代码
多行,因为它太长了。将文本分成列表后,
Python代码将它连接在一起并将其与原始代码进行比较
确保它是正确的。但是,破坏文本的代码会丢失
相邻的空间导致错误比较。
我在代码中添加了print(argparse.py,Python 2.7):
# wrap the usage parts if it's too long
text_width = self._width - self._current_indent
if len(prefix) + len(usage) > text_width:
# break usage into wrappable parts
part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
opt_usage = format(optionals, groups)
pos_usage = format(positionals, groups)
opt_parts = _re.findall(part_regexp, opt_usage)
pos_parts = _re.findall(part_regexp, pos_usage)
print ' '.join(opt_parts)
print opt_usage
assert ' '.join(opt_parts) == opt_usage
结果:
[-h] -f FIN -o OUT -t TRANS
[-h] -f FIN -o OUT -t TRANS
Traceback (most recent call last):
File "blah.py", line 9, in <module>
args = parser.parse_args()
请注意OUT之后的额外空格。
这解释了所有观察到的行为:
--trans
参数移动--out
到最后否定行为。--out
参数否定了behvaior。答案 1 :(得分:4)
问题不在于您添加的额外-h。查看错误和-o
参数:
assert ' '.join(opt_parts) == opt_usage
它正在加入'--out '
中的空白。如果你删除它,一切都应该正常。
答案 2 :(得分:2)
我带着完全相同的问题/错误来到这里,但在--out
之后没有任何额外的空格。我的问题是metavar被设置为空字符串(metavar=''
)。改变这解决了问题。
答案 3 :(得分:0)
Python 3.5.2
它让我疯了一会儿,但我终于找到了问题。
它肯定是一个使用行长度问题,如果它超过为控制台/终端设置的COLUMNS
环境变量,则会出现该错误。
我从命令行尝试:
$ COLUMNS=80 python <myprog.py> -h
我得到了这个例外:
...
File "/usr/lib/python3.5/argparse.py", line 1735, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "/usr/lib/python3.5/argparse.py", line 1767, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "/usr/lib/python3.5/argparse.py", line 1973, in _parse_known_args
start_index = consume_optional(start_index)
File "/usr/lib/python3.5/argparse.py", line 1913, in consume_optional
take_action(action, args, option_string)
File "/usr/lib/python3.5/argparse.py", line 1841, in take_action
action(self, namespace, argument_values, option_string)
File "/usr/lib/python3.5/argparse.py", line 1025, in __call__
parser.print_help()
File "/usr/lib/python3.5/argparse.py", line 2367, in print_help
self._print_message(self.format_help(), file)
File "/usr/lib/python3.5/argparse.py", line 2351, in format_help
return formatter.format_help()
File "/usr/lib/python3.5/argparse.py", line 287, in format_help
help = self._root_section.format_help()
File "/usr/lib/python3.5/argparse.py", line 217, in format_help
func(*args)
File "/usr/lib/python3.5/argparse.py", line 338, in _format_usage
assert ' '.join(opt_parts) == opt_usage
AssertionError
但是:
$ COLUMNS=<XX> python <myprog.py> -h
其中XX>得到的使用线,一切正常,它打印使用+帮助和退出。
因此,要么缩短使用行,要么增加COLUMNS
值。
修改强>
我在我的案例中发现了错误:我在程序/参数说明中使用了方括号[]
。
正如其他人正确指出的那样,查看发生异常的python代码,您可以看到argparse有一个自动将使用/帮助折叠到$COLUMNS
列的规定。
但要分割长行,它使用以下RE:
(文件&#34; /usr/lib/python3.5/argparse.py",第333行:)
`part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'`
当它重新加入要检查的行时,如果用户引入了方括号,则断言失败,因为它们是argparse用来标记可选值的特殊字符。
简而言之,我从文本中删除了流氓方括号,一切正常,使用/帮助正确折叠并根据$COLUMNS
值进行格式化。
答案 4 :(得分:0)
对我来说,它同时设置了required = True和metavar =''。删除其中一个并保留另一个即可解决。