简体   繁体   English

Python argparse AssertionError

[英]Python argparse AssertionError

I just started using argparse module. 我刚开始使用argparse模块。 I wrote the following reduced snippet to demonstrate an issue I'm having. 我编写了以下简化代码片段来演示我遇到的问题。

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)))

AssertionError will be produced when script is run with argument -h 使用参数-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

Reducing the length of the description string passed to ArgumentParser makes it work correctly. 减少传递给ArgumentParser的描述字符串的长度使其正常工作。 Removing one of the arguments will also help. 删除其中一个参数也会有所帮助。

Am I doing something wrong here? 我在这里做错了吗? My environment is: 我的环境是:

Python 3.3.5 |Anaconda 1.9.2 (64-bit)| Python 3.3.5 | Anaconda 1.9.2(64位)| (default, Mar 10 2014, 11:25:04) [MSC v.1600 64 bit (AMD64)] on win32 (默认情况下,2014年3月10日,11:25:04)[winv上的MSC v.1600 64位(AMD64)]

There is an extra space after --out in the code. 代码中的--out有一个额外的空格。 Change: 更改:

parser.add_argument('-o', '--out ', help='b', required = True)

to: 至:

parser.add_argument('-o', '--out', help='b', required = True)

The underlying cause of the problem is an assert check within the Python code that only occurs when Python attempts to break the help text into multiple lines because it is too long. 问题的根本原因是Python代码中的assert检查只有在Python试图将帮助文本分成多行时才会发生,因为它太长了。 After breaking the text into a list, the Python code joins it back together and compares it to the original to ensure that it is correct. 在将文本分成列表之后,Python代码将它连接在一起并将其与原始文件进行比较以确保它是正确的。 However, the code that breaks the text apart drops the adjoining spaces resulting in a miscompare. 但是,将文本分开的代码会丢弃相邻的空格,从而导致错误比较。

I added prints to the code (argparse.py, Python 2.7): 我在代码中添加了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

And the results: 结果如下:

[-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()

Note the extra space after OUT. 注意OUT后的额外空间。

This explains all of the observed behavior: 这解释了所有观察到的行为:

  • Must be long enough to trigger the wrapping behavior. 必须足够长才能触发包装行为。
  • Deleting the --trans argument moved --out to the end negating the behavior. 删除--trans参数移动--out到结尾否定行为。
  • Deleting the --out argument negateted the behvaior. 删除--out参数否定了behvaior。

The problem is not the extra -h that you've added. 问题不在于您添加的额外-h。 Look at the error and the -o argument: 查看错误和-o参数:

assert ' '.join(opt_parts) == opt_usage

it's joining the whitespace in '--out ' . 它正在加入'--out '的空白'--out ' If you remove it, everything should work fine. 如果你删除它,一切都应该正常。

I came here with the exact same problem/error, but without having any extra spaces after --out . 我带着完全相同的问题/错误来到这里,但是在--out之后没有任何额外的空格。 My problem was that metavar was set to an empty string ( metavar='' ). 我的问题是metavar被设置为空字符串( metavar='' )。 Changing that resolved the issue. 改变这解决了问题。

Python 3.5.2 Python 3.5.2

It drove me crazy for a while but I've found the problem at last. 它让我疯狂了一段时间,但我终于找到了问题。 It's definitely a usage line length issue, if it exceeds the COLUMNS environment variable set for the console/terminal, you get that error. 这肯定是一个使用行长度问题,如果它超过为控制台/终端设置的COLUMNS环境变量,则会出现该错误。 I try from command line: 我从命令行尝试:

$ COLUMNS=80 python <myprog.py> -h

and I get this exception: 我得到这个例外:

...
  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

But with: 但是:

$ COLUMNS=<XX> python <myprog.py> -h

where XX > of the resulting usage line, everything is ok, it prints the usage + help and exits. 结果使用行的XX>,一切正常,它打印用法+帮助并退出。 So either you shorten your usage line or you increment the COLUMNS value. 因此,要么缩短使用线,要么增加COLUMNS值。

EDIT: 编辑:

I've found the error in my case: I was using the square brackets [] in my program/arguments description. 我在我的案例中发现了错误:我在程序/参数描述中使用了方括号[]

As others have correctly pointed out, looking at the python code where the exception occurred, you can see that argparse has a provision to automatically fold the usage/help to $COLUMNS columns. 正如其他人正确指出的那样,查看发生异常的python代码,您可以看到argparse有一个自动将使用/帮助折叠到$COLUMNS列的规定。 But to split the long rows, it uses the following RE: 但要分割长行,它使用以下RE:

(File "/usr/lib/python3.5/argparse.py", line 333:) (文件“/usr/lib/python3.5/argparse.py”,第333行:)

`part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'`

When it rejoins the line to check, if the user has introduced square brackets, the assert fails, being them special characters used by argparse to mark optional values. 当它重新加入要检查的行时,如果用户引入了方括号,则断言失败,因为它们是argparse用来标记可选值的特殊字符。

In short, I removed the rogue square brackets from my text and everything works fine, with the usage/help properly folded and formatted according to the $COLUMNS value. 简而言之,我从文本中删除了流氓方括号,一切正常,使用/帮助正确折叠并根据$COLUMNS值进行格式化。

For me, it was setting both required=True and metavar=''. 对我来说,它设置了required = True和metavar =''。 Removing one and keeping the other solved it. 删除一个并保持另一个解决它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM