25

-lオプションの引数( )が指定されている場合、通常必要な2つの位置引数が評価されるべきではないという事実をargparseに無視させようとしています。

基本的に、私は --help の動作を再現しようとしています: -h を指定すると、欠落している必要な引数はすべて無視されます。

コード例:

parser = argparse.ArgumentParser(description="Foo bar baz")
parser.add_argument('arg1', help='arg1 is a positional argument that does this')
parser.add_argument('arg2', help='arg2 is a positional argument that does this')
parser.add_argument('-l', '--list', dest='list', help='this is an optional argument that prints stuff')

options, args = parser.parse_args()

if options.list:
   print "I list stuff"

そしてもちろん、今実行すると、次のようになります。

error: too few arguments

のようなさまざまなことを試しnargs='?'ましたが、何も機能しませんでした。

この質問は非常に似ていますが、回答されていません。

4

6 に答える 6

9

残念ながら、これにargparseは十分な柔軟性がありません。あなたができる最善のことはarg1arg2オプションを使用して作成し、必要に応じてnargs="?"それらが与えられているかどうかを自分で確認することです。

内部アクションは、コマンド ラインでまたはが検出helpされるとすぐにヘルプ メッセージを出力してプログラムを終了することによって実装されます。同様のアクションを自分で書くことができます。-h--help

class MyAction(argparse.Action):
    def __call__(self, parser, values, namespace, option_string):
        print "Whatever"
        parser.exit()

(警告: テストされていないコードです!)

ただし、後者のアプローチには明確な欠点があります。ヘルプ メッセージは無条件に表示arg1arg2れ、強制的な引数として表示されます。また、コマンド ラインの解析は、-lorに遭遇すると単純に停止--listし、それ以上の引数は無視されます。この動作はでは問題--helpありませんが、他のオプションでは望ましくありません。

于 2011-09-20T12:36:07.483 に答える
6

この問題に遭遇し、サブコマンドを使用することにしました。サブコマンドはやり過ぎかもしれませんが、プログラムが多くの場合(私が行ったように)位置引数の一部を使用していないことがわかった場合は、サブコマンドが良い解決策になる可能性があります。

あなたの与えられた例のために、私は次のようなものを使うでしょう:

parser = argparse.ArgumentParser(description="Foo bar baz")
subparsers = parser.add_subparsers(description='available subcommands')

parser_main = subparsers.add_parser('<main_command_name>')
parser_main.add_argument('arg1', help='arg1 is a positional argument that does this')
parser_main.add_argument('arg2', help='arg2 is a positional argument that does this')

parser_list = subparsers.add_parser('list', help='this is a subcommand that prints stuff')

options, args = parser.parse_args()

argparseのドキュメントに記載されている(などのset_defaults(func=list))詳細を省略しました。

于 2011-10-21T23:01:36.147 に答える
2

が役立つと思いnargs='*'ます。

位置引数は無視できるためif、位置引数が true または false であることを確認するために使用できます。

http://docs.python.org/library/argparse.html#nargs

于 2012-05-20T05:12:38.163 に答える
1

ここで解決策を見つけたかもしれません。確かに、これは汚いハックですが、機能します。

注: 以下はすべて Python 3.3.2 に適用されます。

回答hereに従って、どのparse_argsアクションが必要かを確認し、それらのいずれかが欠落している場合はエラーをスローします。この動作をオーバーライドすることを提案します。

サブクラス化することにより、いくつかの引数が欠落しているためにエラーがスローされたかどうかをチェックし、必要なアクションを実行する新しいメソッド (オリジナルはここにありますArgumentParser) を定義できます。コードは次のとおりです。ArgumentParser.error

import argparse
import sys
from gettext import gettext as _

class ArgumentParser(argparse.ArgumentParser):
    skip_list = []

    def error(self, message):
        # Let's see if we are missing arguments
        if message.startswith('the following arguments are required:'):
            missingArgs = message.split('required: ')[1].split(', ')
            newArgs = []    # Creating a list of whatever we should not skip but is missing
            for arg in missingArgs:
                if arg not in self.skip_list:
                    newArgs.append(arg)
                else:
                    self.skip_list.remove(arg)  # No need for it anymore
            if len(newArgs) == 0:
                return  # WARNING! UNTESTED! MAY LEAD TO SPACETIME MELTDOWN!
            else:   # Some required stuff is still missing, so we show a corrected error message
                message = _('the following arguments are required: %s') % ', '.join(newArgs)

        self.print_usage(sys.stderr)    # Original method behavior
        args = {'prog': self.prog, 'message': message}
        self.exit(2, _('%(prog)s: error: %(message)s\n') % args)

新しいメソッドは、最初にエラーがコマンド ラインに引数がないためかどうかをチェックします (エラーを生成するコードについては、こちらを参照してください)。その場合、メソッドはエラー メッセージから引数の名前を取得し、それらをリスト ( missingArgs) に入れます。

次に、このリストを繰り返し処理し、スキップする必要がある引数とまだ必要な引数を確認します。どの引数をスキップするかを決定するために、それらを と比較しますskip_list。これはサブクラスのフィールドでありArgumentParser、パーサーで必要な場合でもスキップする引数の名前が含まれている必要があります。たまたま含まれている引数skip_listは、見つかったときに削除されることに注意してください。

コマンドラインから欠落している必要な引数がまだある場合、メソッドは修正されたエラー メッセージをスローします。ただし、欠落しているすべての引数をスキップする必要がある場合は、メソッドは戻ります。

警告!の元の定義でArgumentParser.errorは、サブクラスでオーバーライドされた場合、 を返すのではなく、終了するか、例外を発生させる必要があります。したがって、ここに示されているものは安全ではない可能性があり、プログラムがクラッシュしたり、コンピューターが発火したり、さらに悪いことに、お茶がすべて蒸発する可能性があります。ただし、この特定のケース (必要な引数がない) では、メソッドから安全に戻ることができるようですしかし、そうではないかもしれません。あなたは警告されました。

埋めるために、次skip_listのようなコードを使用できます。

class SpecialHelp(argparse._HelpAction):
    def __call__(self, parser, namespace, values, option_string=None):
        parser.print_help()
        print()
        for action in parser._actions:
            if action != self and action.required:
                parser.skip_list.append(argparse._get_action_name(action))

この特定のクラスは組み込みhelpアクションを模倣しますが、終了する代わりに、残りの必要な引数をすべて に挿入しskip_listます。

私の答えがお役に立てば幸いです。

于 2013-08-19T05:33:03.560 に答える