この問題については、http://bugs.python.org/issue9334で詳しく説明されています。活動のほとんどは 2011 年に行われました。昨年パッチを追加しましたが、パッチのバックログがかなりありargparseます。
問題となっているのは、 のような文字列の潜在的なあいまいさ'--env'、または"-s WHATEVER -e COOL STUFF"引数を取るオプションに続く場合です。
optparse単純な左から右への解析を行います。1つ目--envは、引数を 1 つ取るオプション フラグであるため、見た目に関係なく、次の引数を消費します。 argparse一方、文字列を 2 回ループします。最初に、それらを 'O' または 'A' (オプション フラグまたは引数) として分類します。2 番目のループでは、relike パターン マッチングを使用して変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)、他の文字列が続く場合はそうではありません。しかし、'-e' フラグとそれに続く文字列 (またはさらに多くのオプション)"-env one two"として解析できるため、問題があります。['-e','nv one two']
--また、後続のすべての文字列を引数として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']
nargsをREMAINDER(not )に変更するとPARSER、その後のすべて-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'*' に似ていますが、フラグのように見えるかどうかに関係なく、後続のすべてを取得します。 最初に like 引数argparse.PARSERを期待するという点で、'+' に似ています。使うpositionalものnargsです。subparsers
この使用法REMAINDERは文書化されています https://docs.python.org/3/library/argparse.html#nargs