Использование 'argparse.ArgumentError' в Python

Я хотел бы использовать исключение ArgumentError в модуле argparse в Python, но я не могу понять, как его использовать. Подпись говорит, что ее следует называть как ArgumentError (аргумент, сообщение) , но я не могу понять, что такое argument . Я думаю, что это должна быть часть объекта парсера, но я не мог найти для него никакой документации.

35
Вы можете использовать его в пользовательском классе Action , как это делают существующие классы. Но я не могу представить причину сделать это за пределами parser . Это ничего особенного - просто добавляет имя Action в сообщение об ошибке. Изучите его использование в коде.
добавлено автор hpaulj, источник
добавлено автор DavidRR, источник

2 ответы

Из исходной документации :

ArgumentError: исключение, созданное объектами ArgumentParser, когда есть ошибки в действиях парсера. Ошибки, возникающие при анализе командной строки, попадают в ArgumentParser и выдаются как сообщения командной строки.

Параметр аргумент конструктора представляет собой объект Action , из которого возникает исключение. Обычно нет необходимости поднять его вне подкласса Action , и при подклассификации его нет необходимости явно выражать его; вы обычно поднимаете ValueError (или что-то подходящее).

Значения плавающего значения от 0 до 1

Что касается вашего комментария, что вы хотите принимать значения с плавающей запятой только между 0 и 1. Для этого вы должны использовать возможность определять настраиваемые типы. Вы можете сделать это, например:

def percentFloat (string):
    value = float(string)
    if value < 0 or value > 1:
        raise argparse.ArgumentTypeError('Value has to be between 0 and 1')
    return value

parser = argparse.ArgumentParser()
parser.add_argument('test', type=percentFloat)
parser.parse_args()

Обратите внимание, что это также безопасно против не-float, поскольку float (string) будет поднимать ValueError для не-float, который также вызывает ошибку недопустимого типа с помощью argparse . ArgumentTypeError - это просто способ указать пользовательское сообщение об ошибке.

Взаимно эксклюзивные параметры

For Взаимно эксклюзивные параметры, you should use argparse.add_mutually_exclusive_group.

Зависимость параметров

Зависимость параметров isn’t really something that should be done by the argument parser. For semantic details, you should instead simply do it yourself:

args = parser.parse_args()
if args.w and not args.p:
    parser.error('-p is required when -w is set.')

Вы можете использовать ArgumentParser.error , чтобы повысить пользовательский сообщение об ошибке, которое прерывает программу и печатает на консоль.

Но, конечно, в такой базовой ситуации было бы гораздо больше смысла просто предполагать -p , если это возможно.

49
добавлено
Это неправильно. Если я просто отправлю значение, я получаю AttributeError: объект «float» не имеет атрибута «option_strings» .
добавлено автор asmeurer, источник
И, кстати, я хочу использовать его, потому что хочу сделать проверку типа, которую модуль напрямую не поддерживает. Например, я хочу, чтобы значение с плавающей запятой находилось в диапазоне от 0 до 1. argparse позволяет указать, что это должно быть float, но мне нужно вручную проверить диапазон. Кажется, что правильная ошибка испускает, когда значение неверно.
добавлено автор asmeurer, источник
Недостаток - это то, что ответ неправильный. ArgumentError (1.1, «Значение вне диапазона») вызывает AttributeError, как я уже упоминал выше. Это должен быть какой-то внутренний объект argparse, но я не могу понять, что. И, кстати, еще один пример того, когда вы захотите сделать это, - это когда вы хотите определить нетривиальную зависимость от аргументов, что, насколько я могу судить, модуль argparse напрямую не поддерживает. Что-то вроде параметра -w требует опции -p , или -n и -N являются взаимоисключающими.
добавлено автор asmeurer, источник
Благодарю. Этот parser.error был тем, что я искал.
добавлено автор asmeurer, источник
@asmeurer Отредактировал мой ответ, чтобы дать вам пример о том, как это сделать.
добавлено автор poke, источник
Обновлен мой ответ.
добавлено автор poke, источник

Хотя parser.error() - это то, что большинство людей, вероятно, хотят, возможно также использовать argparse.ArgumentError() (как задает вопрос.) Вам нужна ссылка на аргумент, например bar_arg в следующем примере:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo')
bar_arg = parser.add_argument('--bar')

args = parser.parse_args()
if args.bar == 'xyzzy':
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")

if args.foo == 'xyzzy':
    parser.error("Can't be 'xyzzy'")

Это приведет к выходу, как показано ниже:

$ python argparse_test.py --foo xyzzy
usage: argparse_test.py [-h] [--foo FOO] [--bar BAR]
argparse_test.py: error: Can't be 'xyzzy'

$ python argparse_test.py --bar xyzzy
Traceback (most recent call last):
  File "argparse_test.py", line 10, in 
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
argparse.ArgumentError: argument --bar: Can't be 'xyzzy'
11
добавлено
Это хороший пример того, как использование ArgumentError вне парсера возможно, но, вероятно, хуже, чем при использовании parser.error .
добавлено автор hpaulj, источник
Хорошо, если вы хорошо напишете свое сообщение об ошибке, то вы наверняка отметили , какой переключатель был оскорбительным. Создание отдельной переменной для каждого добавленного аргумента может быть очень громоздким ...
добавлено автор Praveen, источник
@hpaulj, да, но ArgumentError имеет одно преимущество: он позволяет вам узнать, какой переключатель был оскорбительным.
добавлено автор ukrutt, источник
@Praveen Это вопрос предпочтения, я полагаю. Я предпочитаю, чтобы переменная записывала «« -foo »не может быть« xyzzy », так как я должен помнить, что такое имя ключа (оно не обязательно совпадает с атрибутом args ). Но, честно говоря, я думаю, что parser.error() должен включать по умолчанию имя злоумышленника.
добавлено автор ukrutt, источник
Python
Python
7 654 участник(ов)

Уютный чат для профессионалов, занимающихся поиском питоньих мудростей. Как не получить бан: https://t.me/ru_python/577926

Python beginners
Python beginners
4 449 участник(ов)

Вопросы про Python для чайников. Cпам и троллинг неприемлем. Не злоупотребляйте стикерами. Частозадаваемые вопросы: https://github.com/ru-python-beginners/faq/blob/master/README.md Статистика тут: https://grstats.me/chat/x4qym2k5uvfkr3al6at7

pro.python
pro.python
1 090 участник(ов)

Сообщество разработчиков под Python Создатель: @rodgelius

Rude Python
Rude Python
971 участник(ов)

Python без „девочек”, здесь матерятся и унижают Django. Not gay friendly. Правила: t.me/rudepython/114107 @rudepython | t.me/rudepython

rupython
rupython
509 участник(ов)

Группа создана с целью оперативного получения ответов на возникающие вопросы по разработке на яп python, смежные темы, а также человеческого общения. Приветствую!

Python-programming
Python-programming
266 участник(ов)

Чат группы вконтакте https://vk.com/python_community