web-dev-qa-db-ja.com

ダッシュを含む引用符付き文字列をargparseに読み取れないのですか?

Argparseに2つの引用符の間の何かを単一の引数として認識させる方法はありますか?ダッシュを見続け、それが新しいオプションの始まりだと仮定しているようです

私のようなものがあります:

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 。 2.7のみであり、optparseではありません。

EDIT4:現在のオープンバグレポートは次のとおりです。 http://bugs.python.org/issue9334

44
sfendell

非常に簡単な回避策として、スペース_python tst.py -e ' -e blah'_で引数を開始できます。単にlstrip()必要に応じて、通常に戻すオプション。

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

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

13
William

更新された回答:

呼び出すときに等号を付けることができます。

python Application.py -env="-env"

元の答え:

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

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

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

そして、サブプロセスに渡す前に、後処理で「+」を「-」に変更します。

47
SethMMorton

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

問題は、'--env'"-s WHATEVER -e COOL STUFF"などの文字列のあいまいさの可能性です。引数を取るオプションに続く場合です。

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

argparseを使用するときの解決策は、引数文字列がオプションフラグと混同されないようにすることです。ここ(およびバグの問題)に示されている可能性は次のとおりです。

--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"'

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

--およびnargs=argparse.PARSERを使用して、argparseに後続のすべての文字列を引数として強制的に表示させることもできます。ただし、引数リストの最後でのみ機能します。

Issue9334には、args_default_to_positional=Trueモードを追加するためのパッチが提案されています。このモードでは、パーサーは、定義された引数と文字列を明確に照合できる場合にのみ、オプションフラグとして文字列を分類します。したがって、「-env --one」の「--one」は引数として分類されます。ただし、「-env --env」の2番目の「--env」は、オプションフラグとして分類されます。


関連するケースの展開

ダッシュ( "-")で始まる引数値でargparseを使用

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)

生産する

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)

「-foo one」の場合は、-foo-fフラグと未指定のエクストラとして解釈されるため失敗します。これは、-fe['-f','-e']として解釈できるようにするアクションと同じです。

nargsREMAINDERPARSERではなく)に変更すると、-eの後のすべてがそのフラグの引数として解釈されます。

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のような引数が必要です。 nargsが使用するsubparsersです。

このREMAINDERの使用は文書化されています。 https://docs.python.org/3/library/argparse.html#nargs

14
hpaulj
paser.add_argument("--argument_name", default=None, nargs=argparse.REMAINDER)

python_file.py --argument_name "--abc = 10 -a = 1 -b = 2 cdef"

注:引数値は二重引用符でのみ渡す必要があり、これは単一引用符では機能しません

0
Gowtham MS