web-dev-qa-db-ja.com

Pythonでは、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()

そして出力:

python simulate_many.py -g 20
Setting up...
Playing games...
....................

負の出力:

python simulate_many.py -g -2
Setting up...
Playing games...

今、明らかに、if args.gamesが負であると判断するifを追加できましたが、自動使用印刷を利用するために、argparseレベルでトラップする方法があるかどうか興味がありました。 。

理想的には、これは次のようなものを出力します:

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'

そのようです:

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'

今のところ私はこれをやっていて、私は幸せだと思う:

if args.games <= 0:
    parser.print_help()
    print "-g/--games: must be positive."
    sys.exit(1)
126
jgritty

これは、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)

これは基本的に、 docs on argparseperfect_square関数からの適合例です。

191
Yuushi

typeは、Yuushiの答えのように、条件/チェックを処理するための推奨オプションです。

特定のケースでは、上限もわかっている場合はchoicesパラメーターを使用することもできます。

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

引数の最小値だけでなく予測可能な最大値がある場合は、範囲を指定してchoicesを使用するのが手っ取り早い方法です。

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

特にargparse.ArgumentParserをサブクラス化する場合は、parse_argsメソッド内から検証を開始するのがより簡単な方法です。

そのようなサブクラス内:

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

この手法は、カスタム呼び出し可能オブジェクトほどクールではないかもしれませんが、仕事はします。


ArgumentParser.error(message) について:

このメソッドは、メッセージを含む使用法メッセージを標準エラーに出力し、ステータスコード2でプログラムを終了します。


クレジット: answer by jonatan

4
Acumenus