a better getopt than getopt.py?

Alex Martelli aleaxit at yahoo.com
Tue Feb 20 13:58:12 CET 2001


"Sean 'Shaleh' Perry" <shaleh at valinux.com> wrote in message
news:mailman.982632084.17484.python-list at python.org...
> Writing my fisrt real python app that people will run from the command
line
> (most of my previous coding has been modules for other software to web
stuff)
> I decided to use getopt.  My setup looks like this:
>
> LONG_OPTIONS = ['help', 'setup-lab', 'lab=']
> SHORT_OPTIONS = 'hS'
>
> try:
>     optlist, args = getopt.getopt(sys.argv[1:], SHORT_OPTIONS,
>                                   LONG_OPTIONS)
> except getopt.error, e:
>     print e
>     print USAGE
>     sys.exit(1)
>
> for option, argument in optlist:
>     if option in ('-h', '--help'):
>         print USAGE
>         sys.exit(0)
>     elif option in ('-S', '--setup-lab'):
>         print 'Want to set up the lab ...'
>     elif option == 'lab':
>         print 'Put lab in: ' + argument
>
> this means I have my options defined twice and then once again in the
USAGE
> output.  Is there not a better way to handle arguments?

I think you basically want to group an option's short-form (if any),
its long-form (if any), and a unique-identifier for the option itself
(off which you can key an if/elif tree) into one 'chunk'.  You can
dress and package this up in several ways, of course, but, at the
root, it will be (before optimization...!-) something like:

Options = ( ('help',      'h',  'H'),
            ('setup-lab', 'S',  'S'),
            ('lab=',      None, 'L')
          )

def long(Options):
    return [long for long, short, unique in Options if not long is None]
def short(Options):
    return [short for long, short, unique in Options if not short is None]
def unique(option, Options):
    def short_to_unique(a_short, Options):
        for long, short, unique in Options:
            if a_short == short: return unique
        return None
    def long_to_unique(a_long, Options):
        for long, short, unique in Options:
            if a_long == long: return unique
        return None
    if option.startswith('--'):
        return long_to_unique(option[2:], Options)
    elif option.startswith('-'):
        return short_to_unique(option[1:], Options)
    else:
        return long_to_unique(option+'=', Options)

and your mainline code becomes, in turn:

try:
    optlist, args = getopt.getopt(sys.argv[1:],
        short(Options), long(Options))
except getopt.error, e:
    print e
    print USAGE
    sys.exit(1)

for option, argument in optlist:
    optionId = unique(option, Options)
    if optionId == 'H':
        print USAGE
        sys.exit(0)
    elif optionId == 'S':
        print 'Want to set up the lab ...'
    elif optionId == 'L':
        print 'Put lab in: ' + argument


Packaging this up as one nice support class or function
allowing a direct (and faster...) loop of the form:

allOpts, args = GetAllOpts(Options)
for optionId, argument in allOpts:
    if optionId == 'H':

etc etc, is left as an easy exercise for the reader:-).


Alex






More information about the Python-list mailing list