[解決済み] Argparse: 引数の数が可変の場合の処理方法 (nargs='*')
質問
私は
nargs='*'
は可変数の引数を処理するのに十分だと思っていました。どうやらそうではないようで、このエラーの原因がわかりません。
コードです。
p = argparse.ArgumentParser()
p.add_argument('pos')
p.add_argument('foo')
p.add_argument('--spam', default=24, type=int, dest='spam')
p.add_argument('vars', nargs='*')
p.parse_args('1 2 --spam 8 8 9'.split())
結果としての名前空間は
Namespace(pos='1', foo='2', spam='8', vars=['8', '9'])
. その代わりに、argparseはこのエラーを出します。
usage: prog.py [-h] [--spam SPAM] pos foo [vars [vars ...]]
error: unrecognized arguments: 9 8
基本的に、argparseはこれらの追加引数をどこに置けばいいのかわかりません...。なぜでしょうか?
どうすれば解決するのでしょうか?
該当するPythonのバグは 課題15112 .
argparse: nargs='*'
位置引数は、オプションと他の位置引数が前にある場合、項目を受け付けません。
argparseが解析するとき
['1', '2', '--spam', '8', '8', '9']
にマッチしようとします。
['1','2']
をできるだけ多くの位置引数でマッチさせようとします。 引数を指定すると、パターンマッチの文字列は
AAA*
: にはそれぞれ1つの引数
pos
と
foo
の引数はゼロ、そして
vars
(ただし
*
はZERO_OR_MOREを意味します)。
['--spam','8']
は、あなたの
--spam
引数によって処理されます。 このため
vars
はすでに
[]
に設定されているので
['8','9']
.
へのプログラミングの変更は
argparse
は
0
の引数文字列はパターンを満たしているが、まだ
optionals
はパースされる。 を処理するのを延期する。
*
引数の処理を延期します。
これを回避するには、まず入力をパースして
parse_known_args
で、次に
remainder
を別の呼び出しで処理し
parse_args
.
位置詞の中にオプション詞を自由に入れられるようにするために
問題 14191
を使うことを提案します。
parse_known_args
のみで
optionals
があり、その後に
parse_args
が続きます。 その
parse_intermixed_args
関数に実装することができます。
ArgumentParser
のサブクラスで実装することができます。
argparse.py
のコード自体を変更することなく
サブパーサーを処理する方法を紹介します。 私は
parse_known_intermixed_args
関数を、体裁を整えるために単純化し、それを
parse_known_args
関数にしました。 再帰を避けるために余分なステップを踏まなければなりませんでした。
最後に私は
_parser_class
を変更し、各サブパーサーはこの代替の
parse_known_args
. 別の方法として、サブクラス
_SubParsersAction
をサブクラス化し、場合によってはその
__call__
.
from argparse import ArgumentParser
def parse_known_intermixed_args(self, args=None, namespace=None):
# self - argparse parser
# simplified from http://bugs.python.org/file30204/test_intermixed.py
parsefn = super(SubParser, self).parse_known_args # avoid recursion
positionals = self._get_positional_actions()
for action in positionals:
# deactivate positionals
action.save_nargs = action.nargs
action.nargs = 0
namespace, remaining_args = parsefn(args, namespace)
for action in positionals:
# remove the empty positional values from namespace
if hasattr(namespace, action.dest):
delattr(namespace, action.dest)
for action in positionals:
action.nargs = action.save_nargs
# parse positionals
namespace, extras = parsefn(remaining_args, namespace)
return namespace, extras
class SubParser(ArgumentParser):
parse_known_args = parse_known_intermixed_args
parser = ArgumentParser()
parser.add_argument('foo')
sp = parser.add_subparsers(dest='cmd')
sp._parser_class = SubParser # use different parser class for subparsers
spp1 = sp.add_parser('cmd1')
spp1.add_argument('-x')
spp1.add_argument('bar')
spp1.add_argument('vars',nargs='*')
print parser.parse_args('foo cmd1 bar -x one 8 9'.split())
# Namespace(bar='bar', cmd='cmd1', foo='foo', vars=['8', '9'], x='one')
関連
-
[解決済み] 変数を参照渡しする方法を教えてください。
-
[解決済み] 環境変数の値にアクセスする方法
-
[解決済み] リストの要素数を取得する方法
-
[解決済み] 文字列が数値(float)であるかどうかを確認するにはどうすればよいですか?
-
[解決済み] Argparse オプションの位置引数?
-
[解決済み] argparseでコマンドラインの引数としてリストを渡すにはどうしたらいいですか?
-
[解決済み] Python argparse 引数なしのコマンドラインフラグ
-
[解決済み] argparseのヘルプテキストに改行を挿入するには?
-
[解決済み】Argparse: 必須引数が「オプション引数」の下に表示される?
-
[解決済み] djangoのQueryDictをPythonのDictに変更するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pandasのデータフレームでタプルの列を分割するにはどうしたらいいですか?
-
[解決済み] 2つの線分が交差しているかどうかを確認するにはどうすればよいですか?
-
[解決済み] PythonでSVGからPNGに変換する
-
[解決済み] タプルのリストを複数のリストに変換するには?
-
[解決済み] Python 2.7サポート終了?
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] subprocess.run()の出力を抑制またはキャプチャするには?
-
[解決済み] Pythonの検索パスを他のソースに展開する
-
[解決済み] pipの依存性/必要条件をリストアップする方法はありますか?