2013-09-04 17 views
7

私は明らかに何かを見逃しているに違いありません。目標は、必要な最初のパラメータ、2番目のオプション、および残りの任意の残りのパラメータを指定してargparseを使用することです。Python argparse:オプションのパラメータをnargs = argparse.REMAINDERと組み合わせる

私は2つのテストパーサーを作成しました。それらの間の唯一の違いは、一方でnargs = argparse.REMAINDERを使用し、他方でnargs = '*'を使用することです。

def doParser1(argsin): 
    parser = argparse.ArgumentParser(description='Parser demo.') 
    parser.add_argument('req1', help='first required parameter') 
    parser.add_argument('--opt1', help='first optional parameter') 
    parser.add_argument('leftovers', nargs=argparse.REMAINDER, 
        help='all the other parameters') 
    argsout = parser.parse_args(args=argsin) 
    print argsout 
    return argsout 

def doParser2(argsin): 
    parser = argparse.ArgumentParser(description='Parser demo.') 
    parser.add_argument('req1', help='first required parameter') 
    parser.add_argument('--opt1', help='first optional parameter') 
    parser.add_argument('leftovers', nargs='*', 
        help='all the other parameters') 
    argsout = parser.parse_args(args=argsin) 
    print argsout 
    return argsout 

余分なパラメータがない場合、parser2が機能します。これはparser1と、パーサー1に続いて入力されている:

input: ['req1value', '--opt1', 'opt1value'] 
Namespace(leftovers=['--opt1', 'opt1value'], opt1=None, req1='req1value') 
Namespace(leftovers=None, opt1='opt1value', req1='req1value') 

余分なパラメータがある場合は、OPT1値がparser1とparser2でミスしただけで混乱します:

input: ['req1value', '--opt1', 'opt1value', 'r1', 'r2'] 
Namespace(leftovers=['--opt1', 'opt1value', 'r1', 'r2'], opt1=None, req1='req1value') 
usage: py-argparse.py [-h] [--opt1 OPT1] 
        [-leftovers [LEFTOVERS [LEFTOVERS ...]]] 
        req1 
py-argparse.py: error: unrecognized arguments: r1 r2 

予想される出力は次のようになります。

Namespace(leftovers=['r1', 'r2'], opt1='opt1value', req1='req1value') 

これは単純なケースである必要があります。ここにあるものは、私が本当にやろうとしていることから単純化されているようです。私は残り物をオプションにして、さまざまなオプションを追加しようとしましたが、何もうまくいきません。

ご協力いただければ幸いです。

答えて

3

--opt1は、 "名前のない"引数の前に来る必要があります。あなたの本当のテストケースは次のようになります。

['--opt1', 'opt1value', 'req1value'] 

['--opt1', 'opt1value', 'req1value', 'r1', 'r2'] 
+0

私はそれが何か単純でなければならないことを知っていました。どこにいてもドキュメントでは見えませんでしたが、nargs = argparse.REMAINDERで動作します。ありがとう。 – OPunWide

4

あなたはparse_known_argsを使用することができます。

import argparse 
parser = argparse.ArgumentParser(description='Parser demo.') 
parser.add_argument('req1', help='first required parameter') 
parser.add_argument('--opt1', help='first optional parameter') 

args, leftovers = parser.parse_known_args(['req1value', '--opt1', 'opt1value']) 
print(args, leftovers) 
# (Namespace(opt1='opt1value', req1='req1value'), []) 

args, leftovers = parser.parse_known_args(['req1value', '--opt1', 'opt1value', 'r1', 'r2']) 
print(args, leftovers) 
# (Namespace(opt1='opt1value', req1='req1value'), ['r1', 'r2']) 
+0

これを後で保存します。もう一つの答えは私が必要なものに合っていた。このソリューションは、最初にオプションを必要としないようですね、そうですか? – OPunWide

+0

右。これは任意の順序で引数を受け入れます。一致しないものは「残り物」になります。 – unutbu

+0

良い解決策。しかし、以前の* remainder *はもはやドキュメンテーション/ヘルプに表示されません。 – hitzg

2

ときpositionalsの一つ以上のpositionalsとoptionalsの間混合がトリッキーです'0以上'タイプ(? * REMAINDER)です。単純な解決策は、それらを混ぜ合わせることではなく、オプションを最初に与え、その後すべてのポジションを与えることです。そのためパーサは最初positionalsのために解析しreq1value文字列の

input: ['req1value', '--opt1', 'opt1value'] 
Namespace(leftovers=['--opt1', 'opt1value'], opt1=None, req1='req1value') 

:ここ

は何が起こっているのです。 req1は1文字列、leftoversグラブその他のものはすべて--opt1を含んでいます。 *leftovers

Namespace(leftovers=None, opt1='opt1value', req1='req1value') 

(実際に私は[]を取得)、それ故に何の文字列、None[]に満足していません。 --opt1はオプションとして解析されます。

input: ['req1value', '--opt1', 'opt1value', 'r1', 'r2'] 
... 
py-argparse.py: error: unrecognized arguments: r1 r2 

leftovers*以前のようには[]に設定されています。 -opt1が処理されます。しかし、今は2つの弦があり、置く場所はありません。あなたは彼らにleftoversに行くことを意図しましたが、それはすでに使用されていました。 leftovers+の場合は、意図したとおりに撮影していたはずです。

キーは、1番目の位置を解析しようとすると、それができるすべての位置を解析しようとします。 1つのレベルでparse_argsは、グループ('A', '')を生成するre.match('(A)(A*)','AOA')を実行しています。

この問題に対処する2つの提案パッチがあります。オプションとポジションの完全な混合を可能にするには、2つのステップparse_known_argsを使用します。これは、optparseのユーザーが期待するような行動のようなものです。

もう1つのパッチは、0引数文字列http://bugs.python.org/issue15112を受け入れることができるポジションの処理を遅延させようとします。

関連する問題