Is there anyway to persuade python's getopt to handle optional parameters to options?

14,481

Solution 1

getopt doesn't support optional parameters. in case of long option you could do:

$ ./testopt.py --verbose=

which will result in empty-string value.

You could find argparse module to be more flexible.

Solution 2

Unfortunately, there is no way. From the optparse docs:

Typically, a given option either takes an argument or it doesn’t. Lots of people want an “optional option arguments” feature, meaning that some options will take an argument if they see it, and won’t if they don’t. This is somewhat controversial, because it makes parsing ambiguous: if "-a" takes an optional argument and "-b" is another option entirely, how do we interpret "-ab"? Because of this ambiguity, optparse does not support this feature.

EDIT: oops, that is for the optparse module not the getopt module, but the reasoning why neither module has "optional option arguments" is the same for both.

Solution 3

You can do an optional parameter with getopt like this:

import getopt
import sys

longopts, shortopts = getopt.getopt(sys.argv[1:], shortopts='', longopts=['env='])
argDict = dict(longopts)

if argDict.has_key('--env') and argDict['--env'] == 'prod':
    print "production"
else:
    print "sandbox"

Usage:

$ python scratch.py --env=prod
production

$ python scratch.py --env=dev
sandbox

$ python scratch.py
sandbox
Share:
14,481
user1750701
Author by

user1750701

Updated on June 24, 2022

Comments

  • user1750701
    user1750701 about 2 years

    According to the documentation on python's getopt (I think) the options fields should behave as the getopt() function. However I can't seem to enable optional parameters to my code:

    #!/usr/bin/python
    import sys,getopt
    
    if __name__ == "__main__":
        try:
            opts, args = getopt.gnu_getopt(sys.argv[1:], "v::", ["verbose="])
        except getopt.GetoptError, err:
            print str(err)
            sys.exit(1)
    
        for o,a in opts:
            if o in ("-v", "--verbose"):
                if a:
                    verbose=int(a)
                else:
                    verbose=1
                print "verbosity is %d" % (verbose)
    

    Results in:

    $ ./testopt.py -v
    option -v requires argument
    $ ./testopt.py -v 1
    verbosity is 1
    
  • m77r44
    m77r44 over 14 years
    Yeah I just noticed that, classic case of "wrong tab" syndrome. However, I still think this reasoning is relative for getopt too.
  • SilentGhost
    SilentGhost over 14 years
    except from optparser docs was posted by Pynt 45 minutes ago!
  • Glenn Maynard
    Glenn Maynard over 14 years
    Also, long options can have optional arguments unambiguously; "--foo" vs. "--foo=arg". Python's doesn't appear to support this, which is very poor; a symptom of halfway reimplementing something from scratch...
  • Pure Jobs Inc.
    Pure Jobs Inc. over 14 years
    @SilentGhost: In my reading of Pynt's answer, I see nothing recommending optparse over get_opt, which is what I was getting at. Admittedly, I didn't explain that well originally, but have edited to do so.
  • SilentGhost
    SilentGhost over 14 years
    @Glenn: python supports everything, maintainer of optparse doesn't. See my answer for decent module.
  • user1750701
    user1750701 over 14 years
    I had read the optparse docs describing why they didn't support the feature but it wasn't clear for opt. It's a shame as -v or -v 2 is a fairly useful idiom which both perl and C have no problem with.
  • user1750701
    user1750701 over 14 years
    optparse specifically says it does not support optional parameters to options.
  • Pure Jobs Inc.
    Pure Jobs Inc. over 14 years
    @stsquad: Yes, I noted that in the (edited) answer. My point was that you may want to consider optparse instead of get_opt if you're going to do this.
  • Alexej Magura
    Alexej Magura almost 4 years
    Except your example doesn't show you using optional arguments: will --env still work without an accompanying argument?