Використання 'argparse.ArgumentError' у Python

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

35
Ви можете використовувати його в спеціальному класі Action , як і існуючі класи. Але я не можу уявити причин для цього за межами parser . Це нічого особливого - просто додає ім'я Action до повідомлення про помилку. Вивчіть його використання в коді.
додано Автор hpaulj, джерело
додано Автор DavidRR, джерело

2 Відповіді

Від вихідної документації :

ArgumentError: Виняток, викликаний об'єктами ArgumentParser, коли є помилки з діями синтаксичного аналізатора. Помилки, підняті під час синтаксичного аналізу командного рядка, виявляються ArgumentParser і випускаються як повідомлення командного рядка.

Параметр аргумент конструктора є об'єктом Action , з якого виникає виняток. Зазвичай немає необхідності піднімати його поза підкласу Action , і під його підкласу немає необхідності явно піднімати його; зазвичай ви піднімаєте ValueError (або що завгодно).

Значення float від 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 (string) підніме ValueError для не-плаваючих, що також викликає помилку типу 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 дає змогу вказати, що він має бути плаваючою, але я повинен вручну перевірити діапазон. Це здається правильною помилкою для випуску, коли значення неправильне.
додано Автор asmeurer, джерело
Опубліковано тому, що відповідь неправильна. ArgumentError (1.1, "Значення поза діапазоном") підвищує AttributeError, як я вже згадував вище. Це має бути якийсь внутрішній аргумент, але я не можу зрозуміти, що. І, до речі, ще одним прикладом, коли ви захочете це зробити, є те, що ви хочете визначити нетривіальну залежність від аргументів, які, наскільки я можу сказати, модуль 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" ", тому що я повинен пам'ятати, що було власне ім'я перемикача (не обов'язково це те саме, що атрибут ). Але, чесно кажучи, я думаю, parser.error() повинна за замовчуванням включати ім'я перемикача.
додано Автор ukrutt, джерело
ІТ КПІ - Python
ІТ КПІ - Python
625 учасників

Канал обговорень про всякі штуки зі світу пайтону. Прохання: 0. мати повагу одне до одного; 1. не матюкатися в сторону людей; 2. не захламляти тред повідомленнями по одному слову;