この問題については、http://bugs.python.org/issue9334で詳しく説明されています。活動のほとんどは 2011 年に行われました。昨年パッチを追加しましたが、パッチのバックログがかなりありargparse
ます。
問題となっているのは、 のような文字列の潜在的なあいまいさ'--env'
、または"-s WHATEVER -e COOL STUFF"
引数を取るオプションに続く場合です。
optparse
単純な左から右への解析を行います。1つ目--env
は、引数を 1 つ取るオプション フラグであるため、見た目に関係なく、次の引数を消費します。 argparse
一方、文字列を 2 回ループします。最初に、それらを 'O' または 'A' (オプション フラグまたは引数) として分類します。2 番目のループでは、re
like パターン マッチングを使用して変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