Search code examples
pythonoptparse

optparse - why the last char of the option can be ignored? With `--file` it behaves same as `--fil`


Here is simple example of code:

from optparse import OptionParser

parser = OptionParser()
parser.add_option("-f", "--file", dest="filename")

(options, args) = parser.parse_args()
print options

I have saved it to file and run. It works:

$ python script.py --file some_name
{'filename': 'some_name'}

But here is the trick:

$ python script.py --fil some_name
{'filename': 'some_name'}

It also works with undeclared option fil. Why it behaves in that way?


Solution

  • You can see how optparse works by opening the optparse.py file in your python install.

    On windows this was:

    C:\Python27\Lib\optparse.py

    The _match_abbrev function is on line 1675:

    def _match_abbrev(s, wordmap):
        """_match_abbrev(s : string, wordmap : {string : Option}) -> string
    
        Return the string key in 'wordmap' for which 's' is an unambiguous
        abbreviation.  If 's' is found to be ambiguous or doesn't match any of
        'words', raise BadOptionError.
        """
        # Is there an exact match?
        if s in wordmap:
            return s
        else:
            # Isolate all words with s as a prefix.
            possibilities = [word for word in wordmap.keys()
                             if word.startswith(s)]
            # No exact match, so there had better be just one possibility.
            if len(possibilities) == 1:
                return possibilities[0]
            elif not possibilities:
                raise BadOptionError(s)
            else:
                # More than one possible completion: ambiguous prefix.
                possibilities.sort()
                raise AmbiguousOptionError(s, possibilities)
    

    Which is called by _match_long_opt which is called by _process_long_opt

    This appears to be documented in this section of the documentation:

    opt_str

    is the option string seen on the command-line that’s triggering the callback. (If an abbreviated long option was used, opt_str will be the full, canonical option string—e.g. if the user puts --foo on the command-line as an abbreviation for --foobar, then opt_str will be "--foobar".)

    If we changed the example you have provided to:

    from optparse import OptionParser
    
    parser = OptionParser()
    parser.disable_interspersed_args()
    parser.add_option("-f", "--file", dest="filename")
    parser.add_option("-z", "--film", dest="filmname")
    
    (options, args) = parser.parse_args()
    print options
    

    With the test case of --fil, you get an error:

    error: ambiguous option: --fil (--file, --film?)
    

    So its ok to use shorter names but if there is any ambiguity optparse will stop.