Python argparse AssertionError
Я только начал использовать модуль 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)))
AssertionError
будет производиться, когда script запускается с аргументом -h
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
Уменьшение длины строки описания, переданной в АргументПарсер, заставляет ее работать правильно. Удаление одного из аргументов также поможет.
Я делаю что-то неправильно здесь? Моя среда:
Python 3.3.5 | Anaconda 1.9.2 (64-бит) | (по умолчанию, 10 марта 2014 года, 11:25:04) [MSC v.1600 64 бит (AMD64)] на win32
Ответы
Ответ 1
В коде есть дополнительное пространство после --out
. Изменение:
parser.add_argument('-o', '--out ', help='b', required = True)
в
parser.add_argument('-o', '--out', help='b', required = True)
Основной причиной проблемы является проверка assert
внутри Python
код, который возникает только тогда, когда Python пытается разбить текст справки на
несколько строк, потому что он слишком длинный. После разбиения текста на список,
код Python соединяет его вместе и сравнивает его с оригиналом
убедитесь, что это правильно. Однако код, который разрывает текст, падает
смежные пространства, что приводит к ошибке.
Я добавил отпечатки к коду (argparse.py, Python 2.7):
# wrap the usage parts if it 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
отрицает поведение.
Ответ 2
Проблема не в добавлении -h, которое вы добавили. Посмотрите на ошибку и аргумент -o
:
assert ' '.join(opt_parts) == opt_usage
он присоединяется к пробелу в '--out '
. Если вы его удалите, все должно работать нормально.
Ответ 3
Я пришел сюда с точно такой же проблемой/ошибкой, но без лишних пробелов после --out
. Моя проблема заключалась в том, что для metavar была задана пустая строка (metavar=''
). Изменение, которое решило проблему.
Ответ 4
Python 3.5.2
Некоторое время это сводило меня с ума, но я наконец нашел проблему. Это определенно проблема длины строки использования, если она превышает COLUMNS
среды 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:
(Файл "/usr/lib/python3.5/argparse.py", строка 333 :)
'part_regexp = r'\(.*?\)+|\[.*?\]+|\S+''
Когда он присоединяется к строке, чтобы проверить, ввел ли пользователь квадратные скобки, assert завершается неудачей, будучи специальными символами, используемыми argparse для обозначения необязательных значений.
Короче говоря, я удалил квадратные квадратные скобки из своего текста, и все работает нормально, с использованием/справкой, правильно сложенным и отформатированным в соответствии со значением $COLUMNS
.
Ответ 5
Для меня это было установка обоих обязательных = True и metavar = ''. Удаление одного и сохранение другого решило это.