2013-04-23 1 views
33

argparseに2つの引用符の間の何かを単一の引数として認識させる方法はありますか?引用符で囲まれた文字列をダッシュ​​で読み取るためにargparseを取得できませんか?

mainparser = argparse.ArgumentParser() 
subparsers = mainparser.add_subparsers(dest='subcommand') 
parser = subparsers.add_parser('queue') 
parser.add_argument('-env', '--extraEnvVars', type=str, 
         help='String of extra arguments to be passed to model.') 
...other arguments added to parser... 

しかし、私は実行すると::

python Application.py queue -env "-s WHATEVER -e COOL STUFF" 

それは私に与える:

を私のような何かを持ってダッシュを見て、それが新しいオプション

のスタートだと仮定しておくように見えます

Application.py queue: error: argument -env/--extraEnvVars: expected one argument 

最初のダッシュを省略すると、それは完全にうまく動作しますが、私ができることは非常に重要ですその中にダッシュを入れた文字列を渡します。私はそれを成功させるが、\を引数の文字列に追加する\でエスケープしようとしました。誰もこれを回避する方法を知っていますか?これは、-sがパーサの引数であるかどうかにかかわらず発生します。

編集:私はPython 2.7を使用しています。

EDIT2:

python Application.py -env " -env" 

完全に正常に動作しますが、

python Application.py -env "-env" 

にはありません。

EDIT3:実際にはすでに討議されているバグです:http://www.gossamer-threads.com/lists/python/bugs/89529http://python.6.x6.nabble.com/issue9334-argparse-does-not-accept-options-taking-arguments-beginning-with-dash-regression-from-optp-td578790.html。それはoptparseではなく、2.7でしかありません。

EDIT4:現在開いているバグ報告は次のとおりです。http://bugs.python.org/issue9334

+0

https://docs.python.org/3/library/argparse.html#nargsを使用しているのPythonのバージョンは何

これは文書化されてREMAINDERの使用、? – William

+0

私はPython 2.7を使用しています。 – sfendell

+0

これはPython 2.7でうまく動作します。他の*引数が設定されていますか? –

答えて

9

非常に簡単な回避策として、引数をスペースpython tst.py -e ' -e blah'で開始することができます。単純にlstrip()オプションを元の状態に戻すことができます。

また、最初の「サブ引数」が元の関数の有効な引数でない場合は、何もする必要はありません。つまり、python tst.py -e '-s hi -e blah'が機能しない唯一の理由は、-stst.pyの有効なオプションであるためです。

また、非推奨のoptparseモジュールも問題なく動作します。

+0

-sがサブパーザーの有効なオプションであるため、私はそれが起こるとは思わない。私はそれを試しました python Application.py queue -e "-notarealoption" と同じエラーが発生しました。 私はlstripを+と置き換えるよりも少しうまくいくのが好きです - SethMMortonのように提案されていますが、実際には文字列を引用する方法はありません。 – sfendell

+1

本当に?私はちょうど私の短いテストからのその仮定に基づいていました。私は1つの引数 '-a'をとり、' -a '-b hello''を送信したスクリプトを作成しましたが、うまくいきました。しかし、私はPythonの別のバージョンを使用していると思います。 – William

+1

私は私の元の質問を編集しました。明らかに、これは> 2.7のargparseの既知のバグです。(私がparserを呼び出す前にsys.argvを変更しました。parse_args()を使用して、-envオプションの先頭にダミー文字を追加し、後でそれを取り除きます。それは地獄のようにハッキーではないが、最終的に私が望むものを得た。 – sfendell

33

更新答え:

あなたはそれを呼び出すとき等号置くことができます。

python Application.py -env="-env" 

オリジナル答え:

私もあなたがやろうとしていることをやっているのですが、parse_known_argsメソッドであるargparseの回避策があります。これにより、定義していないすべての引数が、サブプロセスに使用することを想定してパーサを通過します。欠点は、間違った引数でエラーを報告することがなく、オプションとサブプロセスのオプションが衝突していないことを確認する必要があることです。

python Application.py -e "+s WHATEVER +e COOL STUFF" 

、その後、あなたは「+」に変更「 - 」後処理であなたのサブプロセスに渡す前に:

別のオプションではなく、マイナスのプラスを使用して、ユーザのを強制することができます。

+1

私はparse_known_argsが私を助けるとは思わない。私は引用符で議論を読むことを全く考えていません。引用符で囲まれた文字列を単一のオブジェクトとして-envに渡したいと思います。 私は後処理ルートを検討しましたが、私はここからより良い答えを得ることはできませんが、ハッキーと感じます。文字列の+文字が - に変更されたことを意味します。私は本当にそれに文字を含む文字列を渡すことが本当に好きです。 – sfendell

+1

私はあなたが何を求めているのかを見ています...引用符なしで複数の文字列を読みたい場合は、 '-nvs = '+''を使って '-env'に1つ以上の文字列を読み込ませるように指示します。 – SethMMorton

+0

しかし、これらの文字列の中には、サブパネルの引数と同じ名前を持つこともありますが、それらの文字列の中にダッシュを付けることもできます。 PythonのようなものApplication.py queue -env "-env blah"はうまくいくはずです。 – sfendell

11

この問題は、http://bugs.python.org/issue9334で詳細に説明されています。ほとんどの活動は2011年に行われました。去年パッチを追加しましたが、​​パッチのバックログがかなりあります。

'--env'、または"-s WHATEVER -e COOL STUFF"のような文字列の潜在的なあいまいさは、引数をとるオプションの後にあると問題になります。

optparse単純な左から右への解析を行います。最初の--envは、1つの引数を取るオプションフラグです。したがって、それは見た目に関係なく、次のものを消費します。一方、​​は、文字列を2回ループします。まず、それらを 'O'または 'A'(オプションフラグまたは引数)として分類します。 2番目のループでは、変数nargsの値を処理するためにreのようなパターンマッチングを使用して、それらを消費します。この場合、OO、2つのフラグ、および引数がないようです。

​​を使用する場合の解決方法は、引数文字列がオプションフラグと混同されないようにすることです。ここに(とバグの問題で)示されている可能性が含まれます:自体'--env'ことで

--env="--env" # clearly defines the argument. 

--env " --env" # other non - character 
--env "--env " # space after 

--env "--env one two" # but not '--env "-env one two"' 

フラグ(引用された場合でも、sys.argvを参照)のように見えますが、他の文字列が続いたときにそれはしていません。しかし、"-env one two"には、['-e','nv one two']、 `-e 'フラグの後に文字列(あるいはそれ以上のオプション)が続くと解析できるので問題があります。

--およびnargs=argparse.PARSERも、次のすべての文字列を引数として表示させるために使用することができます(​​)。しかし、彼らは引数リストの最後でのみ動作します。

問題9334には、args_default_to_positional=Trueモードを追加するためのパッチが提案されています。このモードでは、パーザは文字列を定義済みの引数と明確に一致させることができる場合にのみ、文字列をオプションフラグとして分類します。したがって、 '--env --one'の'one 'は引数として分類されます。しかし、 '--env --env'の2番目の ' - env'は引き続きオプションフラグとして分類されます。

Using argparse with argument values that begin with a dash ("-")

parser = argparse.ArgumentParser(prog="PROG") 
parser.add_argument("-f", "--force", default=False, action="store_true") 
parser.add_argument("-e", "--extra") 
args = parser.parse_args() 
print(args) 

に関連する場合に拡張


-foo-fフラグとして解釈されるので "-fooつ" の場合に障害が発生した

1513:~/mypy$ python3 stack16174992.py --extra "--foo one" 
Namespace(extra='--foo one', force=False) 
1513:~/mypy$ python3 stack16174992.py --extra "-foo one" 
usage: PROG [-h] [-f] [-e EXTRA] 
PROG: error: argument -e/--extra: expected one argument 
1513:~/mypy$ python3 stack16174992.py --extra "-bar one" 
Namespace(extra='-bar one', force=False) 
1514:~/mypy$ python3 stack16174992.py -fe one 
Namespace(extra='one', force=True) 

を生成しますプラス不特定のエクストラ。これは、-fe['-f','-e']と解釈するのと同じ動作です。

-eは、そのフラグの引数として解釈された後、私はnargsREMAINDERに(ないPARSER)、すべてを変更する場合:

parser.add_argument("-e", "--extra", nargs=argparse.REMAINDER) 

すべての例の仕事。値はリストであることに注意してください。そして、引用符は必要ありません:それは旗のように見えるかどうかかどうか、以下のすべてを取る以外

1518:~/mypy$ python3 stack16174992.py --extra "--foo one" 
Namespace(extra=['--foo one'], force=False) 
1519:~/mypy$ python3 stack16174992.py --extra "-foo one" 
Namespace(extra=['-foo one'], force=False) 
1519:~/mypy$ python3 stack16174992.py --extra "-bar one" 
Namespace(extra=['-bar one'], force=False) 
1519:~/mypy$ python3 stack16174992.py -fe one 
Namespace(extra=['one'], force=True) 
1520:~/mypy$ python3 stack16174992.py --extra --foo one 
Namespace(extra=['--foo', 'one'], force=False) 
1521:~/mypy$ python3 stack16174992.py --extra -foo one 
Namespace(extra=['-foo', 'one'], force=False) 

argparse.REMAINDERは、「*」のようなものです。 argparse.PARSERは、最初にpositionalのような引数が必要であるという点で、 '+'とよく似ています。 subparsersが使用するのはnargsです。あなたは

+2

ありがとうございます: 'nargs = argparse.PARSER'が私を助けました。 – guettli

+0

私は何が変わったのかよく分かりませんが、今は 'python Application.py queue -env" -s WHATEVER -e COOL STUFF "が動作します。スタンドアロンの '-foo'(または '--foo')はまだフラグとして解釈されるため、 'queue -env" -foo "'はエラーを発生させます。 apprentの旗の後のスペースは違いを生みます。 – hpaulj

関連する問題