programing

argparse로 구문 분석된 값을 어떻게 제한할 수 있습니까(예: 정수를 양의 값으로 제한)?

starjava 2023. 7. 11. 21:23
반응형

argparse로 구문 분석된 값을 어떻게 제한할 수 있습니까(예: 정수를 양의 값으로 제한)?

지금까지 이 코드를 가지고 있습니다.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-g", "--games", type=int, default=162,
                    help="The number of games to simulate")
args = parser.parse_args()

경기수에 대하여 음의 값을 제공하는 것은 이치에 맞지 않으나,type=int모든 정수를 허용합니다.예를 들어, 실행 중인 경우python simulate_many.py -g -2,args.games로 설정됩니다.-2아무 문제가 없는 것처럼 프로그램이 계속 진행됩니다.

저는 제가 단지 그 가치를 분명히 확인할 수 있다는 것을 깨달았습니다.args.games인수를 구문 분석한 후.하지만 제가 스스로 이 상태를 확인할 수 있을까요? 어떻게요?

자동 사용 메시지가 사용자에게 요구 사항을 설명할 수 있도록 그렇게 작동했으면 합니다.이상적으로 출력은 다음과 같습니다.

python simulate_many.py -g -2
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid positive int value: '-2'

현재 정수로 변환할 수 없는 인수를 처리하는 것처럼:

python simulate_many.py -g a
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid int value: 'a'

이는 다음을 활용하여 가능해야 합니다.type이를 결정하는 실제 방법을 정의해야 합니다.

def check_positive(value):
    ivalue = int(value)
    if ivalue <= 0:
        raise argparse.ArgumentTypeError("%s is an invalid positive int value" % value)
    return ivalue

parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=check_positive)

이것은 기본적으로 단지 적응된 예입니다.perfect_square의 문서에 있는 기능argparse.

typeYuushi의 답변과 같이 조건/체크를 처리하는 데 권장되는 옵션이 될 것입니다.

특정한 경우에는 다음을 사용할 수도 있습니다.choices상한값도 알려진 경우 매개변수:

parser.add_argument('foo', type=int, choices=xrange(5, 10))

참고: 사용range대신에xrangepython 3.x의 경우

빠르고 더러운 방법은, 만약 당신이 당신의 arg에 대한 max와 min을 예측할 수 있다면, 사용하는 것입니다.choices사정거리가 있는

parser.add_argument('foo', type=int, choices=xrange(0, 1000))

Google 검색에서 나와 같은 사람이 이 문제를 발견한 경우 모듈식 접근 방식을 사용하여 지정된 범위에서만 Argparse 정수를 허용하는 보다 일반적인 문제를 깔끔하게 해결하는 방법의 예를 다음에 제시합니다.

# Custom argparse type representing a bounded int
class IntRange:

    def __init__(self, imin=None, imax=None):
        self.imin = imin
        self.imax = imax

    def __call__(self, arg):
        try:
            value = int(arg)
        except ValueError:
            raise self.exception()
        if (self.imin is not None and value < self.imin) or (self.imax is not None and value > self.imax):
            raise self.exception()
        return value

    def exception(self):
        if self.imin is not None and self.imax is not None:
            return argparse.ArgumentTypeError(f"Must be an integer in the range [{self.imin}, {self.imax}]")
        elif self.imin is not None:
            return argparse.ArgumentTypeError(f"Must be an integer >= {self.imin}")
        elif self.imax is not None:
            return argparse.ArgumentTypeError(f"Must be an integer <= {self.imax}")
        else:
            return argparse.ArgumentTypeError("Must be an integer")

이를 통해 다음과 같은 작업을 수행할 수 있습니다.

parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=IntRange(1))     # Must have foo >= 1
parser.add_argument('bar', type=IntRange(1, 7))  # Must have 1 <= bar <= 7

변수foo이제 OP가 요청한 것처럼 양의 정수만 허용합니다.

위의 양식 외에도 최대치도 가능합니다.IntRange:

parser.add_argument('other', type=IntRange(imax=10))  # Must have other <= 10

특히 하위 분류인 경우 더 간단한 대안argparse.ArgumentParser내부에서 유효성 검사를 시작하는 것입니다.parse_args방법.

이러한 하위 클래스 내부:

def parse_args(self, args=None, namespace=None):
    """Parse and validate args."""
    namespace = super().parse_args(args, namespace)
    if namespace.games <= 0:
         raise self.error('The number of games must be a positive integer.')
    return namespace

이 기술은 사용자 지정 통화 케이블만큼 멋지지는 않지만 효과가 있습니다.


정보:

이 방법은 메시지를 포함한 사용 메시지를 표준 오류로 출력하고 상태 코드 2로 프로그램을 종료합니다.


신용: 조나탄의 답변

Yuushi의 답변을 기반으로 다양한 숫자 유형에 대해 숫자가 양수인지 확인할 수 있는 간단한 도우미 기능을 정의할 수도 있습니다.

def positive(numeric_type):
    def require_positive(value):
        number = numeric_type(value)
        if number <= 0:
            raise ArgumentTypeError(f"Number {value} must be positive.")
        return number

    return require_positive

도우미 함수를 사용하여 다음과 같은 숫자 인수 유형에 주석을 달 수 있습니다.

parser = argparse.ArgumentParser(...)
parser.add_argument("positive-integer", type=positive(int))
parser.add_argument("positive-float", type=positive(float))

언급URL : https://stackoverflow.com/questions/14117415/how-can-i-constrain-a-value-parsed-with-argparse-for-example-restrict-an-integ

반응형