38

argparse を使用して、作業中のプログラムのコマンド ライン引数を解析しようとしています。基本的に、オプションの引数内に広がる複数の位置引数をサポートする必要がありますが、この状況では argparse を機能させることができません。実際のプログラムでは、カスタム アクションを使用しています (位置引数が見つかるたびに名前空間のスナップショットを保存する必要があります) が、私が抱えている問題はappendアクションで再現できます。

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-a', action='store_true')
>>> parser.add_argument('-b', action='store_true')
>>> parser.add_argument('input', action='append')
>>> parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
usage: ipython [-h] [-a] [-b] input
ipython: error: unrecognized arguments: filetwo filethree

これが名前空間になるようにしたいのですが、これ(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])を行う方法がわかりません-実際に可能であれば。ドキュメントや Google には、これが可能である場合、何らかの方法でそれが可能であると書かれているものは何も表示されませんが、可能性は十分にあります (可能性は高いですか?) 私は何かを見落としています。誰か提案はありますか?

4

4 に答える 4

31

-aこのように、スイッチ (つまりと-b) を位置引数 (つまり、fileone、filetwo、filethree) とインターリーブすることはできません。スイッチは、位置引数の前後ではなく、前後に指定する必要があります。

nargsまた、複数の位置引数を持つためには、パラメータをに指定する必要がありますadd_argument。例えば:

parser.add_argument('input', nargs='+')

これはargparse、1 つ以上の位置引数を消費してリストに追加するように指示します。詳細については、argparse のドキュメントを参照してください。この行で、コード:

parser.parse_args(['-a', '-b', 'fileone', 'filetwo', 'filethree'])

結果:

Namespace(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])
于 2011-03-21T03:32:34.953 に答える
17

srgerg は、位置引数の定義については正しかった。必要な結果を得るには、それらをオプションの引数として受け入れ、必要に応じて結果の名前空間を変更する必要があります。

カスタム アクションを使用できます。

class MyAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):

        # Set optional arguments to True or False
        if option_string:
            attr = True if values else False
            setattr(namespace, self.dest, attr)

        # Modify value of "input" in the namespace
        if hasattr(namespace, 'input'):
            current_values = getattr(namespace, 'input')
            try:
                current_values.extend(values)
            except AttributeError:
                current_values = values
            finally:
                setattr(namespace, 'input', current_values)
        else:
            setattr(namespace, 'input', values)

parser = argparse.ArgumentParser()
parser.add_argument('-a', nargs='+', action=MyAction)
parser.add_argument('-b', nargs='+', action=MyAction)
parser.add_argument('input', nargs='+', action=MyAction)

そして、これはあなたが得るものです:

>>> parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
Namespace(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])

または、結果の名前空間を次のように変更できます。

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-a', nargs='+')
>>> parser.add_argument('-b', nargs='+')
>>> parser.add_argument('input', nargs='+')
>>> result = parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])

>>> inputs = []
>>> inputs.extend(result.a)
>>> inputs.extend(result.b)
>>> inputs.extend(result.input)

>>> modified = argparse.Namespace(
        a = result.a != [],
        b = result.b != [],
        input = inputs)

そして、これはあなたが得るものです:

>>> modified
Namespace(a=True, b=True, input=['filetwo', 'filethree', 'fileone'])

ただし、どちらの方法もコードの可読性と保守性が低下します。プログラムのロジックを変更して、別の方法で実行する方がよいかもしれません。

于 2011-03-21T05:42:21.263 に答える
3

hpaulj は正しい軌道に乗っているように思えますが、必要以上に複雑になっています。Blair は、古い optparse モジュールの動作に似たものを探しており、args オブジェクトの入力フィールドにある入力引数のリストを実際には必要としていないのではないかと思います。彼はただ望んでいる

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-a', action='store_true')
parser.add_argument('-b', action='store_true')
opts, args = parser.parse_known_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
# Namespace(a=True, b=True), ['fileone', 'filetwo', 'filethree']

optparse の用語では、「オプション」は opts で使用でき、散在する可能性のある他の「引数」のリストは args にあります。

于 2017-07-06T15:56:11.817 に答える