How can I get optparse's OptionParser to ignore invalid options?

后端 未结 5 1905
清歌不尽
清歌不尽 2020-12-09 15:53

In python\'s OptionParser, how can I instruct it to ignore

相关标签:
5条回答
  • 2020-12-09 16:32

    Python 2.7 (which didn't exist when this question was asked) now provides the argparse module. You may be able to use ArgumentParser.parse_known_args() to accomplish the goal of this question.

    0 讨论(0)
  • 2020-12-09 16:32

    Per synack's request in a different answer's comments, I'm posting my hack of a solution which sanitizes the inputs before passing them to the parent 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
    
    0 讨论(0)
  • 2020-12-09 16:35

    This is pass_through.py example from Optik distribution.

    #!/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()
    
    0 讨论(0)
  • 2020-12-09 16:45

    Here's one way to have unknown arguments added to the result args of OptionParser.parse_args, with a simple subclass.

    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)
    

    And here's a snippet to show that it works:

    # 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
    
    0 讨论(0)
  • 2020-12-09 16:46

    By default there is no way to modify the behavior of the call to error() that is raised when an undefined option is passed. From the documentation at the bottom of the section on how optparse handles errors:

    If optparse‘s default error-handling behaviour does not suit your needs, you’ll need to subclass OptionParser and override its exit() and/or error() methods.

    The simplest example of this would be:

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

    This would simply make all calls to error() do nothing. Of course this isn't ideal, but I believe that this illustrates what you'd need to do. Keep in mind the docstring from error() and you should be good to go as you proceed:

    Print a usage message incorporating 'msg' to stderr and exit. If you override this in a subclass, it should not return -- it should either exit or raise an exception.

    0 讨论(0)
提交回复
热议问题