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

2

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?

Preparation answered 5/4, 2016 at 14:51 Comment(2)
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 charactersLinalool
If you don't want the abbreviations, newer versions of argparse (but not the deprecated optparse) allow you to disable it.Compare
B
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.

Bilyeu answered 5/4, 2016 at 15:28 Comment(1)
thanks for detailed response. I should read the documentation more closely next time )Preparation
F
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.

Flashgun answered 5/4, 2016 at 15:5 Comment(0)
B
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.

Bilyeu answered 5/4, 2016 at 15:28 Comment(1)
thanks for detailed response. I should read the documentation more closely next time )Preparation

© 2022 - 2024 — McMap. All rights reserved.