25

PythonでOptionParser、メソッドに提供された未定義のオプションを無視するようにPythonに指示するにはどうすればよいparse_argsですか?

たとえば、インスタンスの
オプションのみを定義しましたが、リストを使用して呼び出します--fooOptionParserparse_args
[ '--foo', '--bar' ]

編集:
元のリストからそれらを除外するかどうかは気にしません。未定義のオプションを無視したいだけです。

これを行う理由は、SConsのAddOptionインターフェイスを使用してカスタムビルドオプションを追加しているためです。ただし、これらのオプションの一部は、ターゲットの宣言をガイドします。したがって、すべてのオプションにアクセスすることなく、スクリプトのさまざまなポイントでsys.argvからそれらを解析する必要があります。最終的に、トップレベルのScons OptionParserは、コマンドラインで未定義のオプションをすべてキャッチします。

4

5 に答える 5

38

単純なサブクラスを使用して、の結果argsに不明な引数を追加する1つの方法を次に示します。OptionParser.parse_args

from optparse import (OptionParser,BadOptionError,AmbiguousOptionError)

class PassThroughOptionParser(OptionParser):
    """
    An unknown option pass-through implementation of OptionParser.

    When unknown arguments are encountered, bundle with largs and try again,
    until rargs is depleted.  

    sys.exit(status) will still be called if a known argument is passed
    incorrectly (e.g. missing arguments or bad argument types, etc.)        
    """
    def _process_args(self, largs, rargs, values):
        while rargs:
            try:
                OptionParser._process_args(self,largs,rargs,values)
            except (BadOptionError,AmbiguousOptionError), e:
                largs.append(e.opt_str)

そして、これが機能することを示すスニペットです。

# Show that the pass-through option parser works.
if __name__ == "__main__": #pragma: no cover
    parser = PassThroughOptionParser()
    parser.add_option('-k', '--known-arg',dest='known_arg',nargs=1, type='int')
    (options,args) = parser.parse_args(['--shazbot','--known-arg=1'])    
    assert args[0] == '--shazbot'
    assert options.known_arg == 1

    (options,args) = parser.parse_args(['--k','4','--batman-and-robin'])
    assert args[0] == '--batman-and-robin'
    assert options.known_arg == 4
于 2012-02-16T07:28:18.043 に答える
11

デフォルトではerror()、未定義のオプションが渡されたときに発生する呼び出しの動作を変更する方法はありません。optparseがエラーを処理する方法に関するセクションの下部にあるドキュメントから:

optparseのデフォルトのエラー処理動作がニーズに合わない場合は、OptionParserをサブクラス化し、exit()メソッドやerror()メソッドをオーバーライドする必要があります。

これの最も簡単な例は次のとおりです。

class MyOptionParser(OptionParser):
    def error(self, msg):
        pass

これは、何もしないようにすべての呼び出しをerror()行うだけです。もちろんこれは理想的ではありませんが、これはあなたがしなければならないことを示していると思います。からのdocstringを覚えておいてください。error()先に進むと、うまくいくはずです。

'msg'を組み込んだ使用法メッセージをstderrに出力して終了します。サブクラスでこれをオーバーライドすると、返されません。終了するか、例外を発生させる必要があります。

于 2009-12-11T01:28:29.460 に答える
7

Python 2.7(この質問が行われたときには存在しませんでした)は、argparseモジュールを提供するようになりました。ArgumentParser.parse_known_args()この質問の目的を達成するために使用できる場合があります。

于 2012-10-05T18:22:19.157 に答える
3

これはOptikディストリビューションpass_through.pyの例です。

#!/usr/bin/env python

# "Pass-through" option parsing -- an OptionParser that ignores
# unknown options and lets them pile up in the leftover argument
# list.  Useful for programs that pass unknown options through
# to a sub-program.

from optparse import OptionParser, BadOptionError

class PassThroughOptionParser(OptionParser):

    def _process_long_opt(self, rargs, values):
        try:
            OptionParser._process_long_opt(self, rargs, values)
        except BadOptionError, err:
            self.largs.append(err.opt_str)

    def _process_short_opts(self, rargs, values):
        try:
            OptionParser._process_short_opts(self, rargs, values)
        except BadOptionError, err:
            self.largs.append(err.opt_str)


def main():
    parser = PassThroughOptionParser()
    parser.add_option("-a", help="some option")
    parser.add_option("-b", help="some other option")
    parser.add_option("--other", action='store_true',
                      help="long option that takes no arg")
    parser.add_option("--value",
                      help="long option that takes an arg")
    (options, args) = parser.parse_args()
    print "options:", options
    print "args:", args

main()
于 2012-12-13T23:21:53.917 に答える
1

別の回答のコメントでのsynackの要求に従って、入力を親に渡す前に入力をサニタイズするソリューションのハックを投稿していますOptionParser

import optparse
import re
import copy
import SCons

class NoErrOptionParser(optparse.OptionParser):
    def __init__(self,*args,**kwargs):
        self.valid_args_cre_list = []
        optparse.OptionParser.__init__(self, *args, **kwargs)

    def error(self,msg):
        pass

    def add_option(self,*args,**kwargs):
        self.valid_args_cre_list.append(re.compile('^'+args[0]+'='))
        optparse.OptionParser.add_option(self, *args, **kwargs)

    def parse_args(self,*args,**kwargs):
        # filter out invalid options
        args_to_parse = args[0]
        new_args_to_parse = []
        for a in args_to_parse:
            for cre in self.valid_args_cre_list:
                if cre.match(a):
                    new_args_to_parse.append(a)


        # nuke old values and insert the new
        while len(args_to_parse) > 0:
            args_to_parse.pop()
        for a in new_args_to_parse:
            args_to_parse.append(a)

        return optparse.OptionParser.parse_args(self,*args,**kwargs)


def AddOption_and_get_NoErrOptionParser( *args, **kwargs):
    apply( SCons.Script.AddOption, args, kwargs)
    no_err_optparser = NoErrOptionParser(optparse.SUPPRESS_USAGE)
    apply(no_err_optparser.add_option, args, kwargs)

    return no_err_optpars
于 2010-01-27T16:56:43.227 に答える