Целочисленное условие Python argparse ( >= 12)

Мне нужно запросить, чтобы аргумент был = = 12, используя argparse.

Я не могу найти способ получить этот результат с помощью argparse, кажется, что нет способа установить правила для данного значения, но только полные наборы принятых значений, таких как выборы = ['rock', 'paper', 'scissors "].

Мой код:

import sys, argparse

parser = argparse.ArgumentParser()
parser.add_argument("-b", "--bandwidth", type=int, help="target bandwidth >=12")
args = parser.parse_args()
if args.bandwidth and args.bandwidth < 12:
    print "ERROR: minimum bandwidth is 12"
    sys.exit(1)

Интересно, есть ли способ получить этот результат напрямую с помощью некоторой опции argparse.

Ответ 1

Один из способов - использовать нестандартный тип.

def bandwidth_type(x):
    x = int(x)
    if x < 12:
        raise argparse.ArgumentTypeError("Minimum bandwidth is 12")
    return x

parser.add_argument("-b", "--bandwidth", type=bandwidth_type, help="target bandwidth >= 12")

Примечание. Я думаю, что ArgumentTypeError является более правильным исключением для повышения, чем ArgumentError. Тем не менее, ArgumentTypeError не задокументирован как открытый класс argparse, и поэтому он не может считаться правильным для использования в вашем собственном коде. Один из вариантов, который мне нравится, заключается в использовании argparse.error, как это делает alecxe в его ответе, хотя я бы использовал пользовательское действие вместо функции типа, чтобы получить доступ к объекту парсера.

Более гибкая опция - это настраиваемое действие, которое обеспечивает доступ к текущему парсеру и пространству имен.

class BandwidthAction(argparse.Action):

    def __call__(self, parser, namespace, values, option_string=None):
        if values < 12:
            parser.error("Minimum bandwidth for {0} is 12".format(option_string))
            #raise argparse.ArgumentError("Minimum bandwidth is 12")

        setattr(namespace, self.dest, values)

parser.add_argument("-b", "--bandwidth", action=BandwidthAction, type=int,
                     help="target bandwidth >= 12")

Ответ 2

вы можете попробовать что-то, что вы вводите в своем объяснении:

import sys, argparse

parser = argparse.ArgumentParser()
parser.add_argument("-b", "--bandwidth", type=int, choices=range(12,100))
args = parser.parse_args()

например, его Argparse, который сам поднимет ошибку с помощью invalid choice

Ответ 3

Вы можете вызвать ошибку парсера без создания пользовательских типов или отдельных функций. Простое изменение вашего примера кода достаточно:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-b", "--bandwidth", type=int, help="target bandwidth >=12")
args = parser.parse_args()
if args.bandwidth and args.bandwidth < 12:
    parser.error("Minimum bandwidth is 12")

Это приведет к выходу приложения и отображению ошибки парсера:

$ python test.py --bandwidth 11 
usage: test.py [-h] [-b BANDWIDTH]
test.py: error: Minimum bandwidth is 12