7

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?

dimadvk
  • 405
  • 3
  • 6
  • Better than that, `--fi` & `--f` work for me too. I'm guessing that as long as there is no ambiguity, you can get away with fewer characters – SiHa Apr 05 '16 at 15:05
  • If you don't want the abbreviations, newer versions of argparse (but not the deprecated optparse) [allow you to disable it](https://stackoverflow.com/questions/33900846/). – Wander Nauta Apr 05 '16 at 15:06

2 Answers2

2

optparse will attempt to match a partial or shorter option against any available longer option names. It's not particularly well documented, but it's always done that. Trying searching for abbrev in https://docs.python.org/2/library/optparse.html#how-callbacks-are-called

Many other option parsing libraries do the same.

Note that optparse is now deprecated.

David Jones
  • 4,766
  • 3
  • 32
  • 45
2

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.

Noelkd
  • 7,686
  • 2
  • 29
  • 43