2013-01-02 6 views
83

タイトルは、私が何をしたいのかを要約しています。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が負であるかを決定する場合、私はちょうど追加することができますが、私は、もし興味がありました自動使用印刷を利用するために、それを​​レベルにトラップする方法がありました。

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

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' 

理想的には、これに似たものを印刷します

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

答えて

120

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

これは基本的に​​上docsperfect_square機能からわずかに適応例です。あなたの引数のための分だけでなく、予測可能な最大を持っている場合

+1

あなたの関数が複数の値を持つことができますか?それはどのように機能するのですか? – Tom

+0

'int'への変換に失敗した場合でも、読み込み可能な出力はありますか?それとも、手動で変換を '試してみる 'べきですか? – NOhs

+2

@MrZ 'error:argument foo:invalid check_positive value:' foo =​​''のようなものがあります。より良いエラーメッセージで例外を再発生させる 'try:' ... 'except ValueError:'を単に追加することができます。 – Yuushi

3

迅速かつ汚い方法は、よう、条件/小切手を処理するための推奨オプションとなり範囲

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

そこには欠点があります。 – jgritty

+3

_dirty_に重点を置いていますね。 –

+2

jgrittyのポイントを明確にするために、choices = xrange(0,1000)を指定すると、--helpを使うたびに、または無効な引数が与えられたときに、1から999までの整数リスト全体がコンソールに書き出されます。ほとんどの状況では良い選択ではありません。 – biomiker

36

typechoicesを使用していますユウシの答えで

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

範囲を生成してサイクリングして入力を検証するので、これはかなり非効率的だと思います。速い 'if'ははるかに高速です。 – TravisThomas

+2

@ trav1th確かにそうかもしれませんが、ドキュメントの使用例です。また、私の答えでは、ゆうしの答えが行くものだと言いました。オプションを与えるのは良いことです。 argparseの場合、実行ごとに1回発生し、ジェネレータ( 'xrange')を使用し、追加のコードは必要ありません。このトレードオフは利用可能です。それぞれの方法を決めて、どちらを行くか決めてください。 – aneroid

+9

ベンの作者の答えでjgrittyのポイントを明確にするために、choices = xrange(0,1000)は、--helpを使うたびに無効な引数があるたびに、1から999までの整数リスト全体をあなたのコンソールに書き出します供給される。ほとんどの状況では良い選択ではありません。 – biomiker

2

シンプルな代替、argparse.ArgumentParserをサブクラス化、parse_argsメソッド内から検証を開始することである場合は特に:あなたの上限も知られている場合は、あなたの特定のケースで

、あなたもchoicesパラメータを使用することができます。

なサブクラス内部:

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)

This method prints a usage message including the message to the standard error and terminates the program with a status code of 2.


クレジット:answer by jonatan

関連する問題