a simple helper class for parsing command line options

Rick Ree rree at nospam-oeb.harvard.edu
Mon Nov 1 21:31:51 EST 1999


I threw this together to make parsing command line options and arguments
a little easier than just using getopt directly.  Feedback welcome.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from getopt import getopt, error
from string import ljust
import sys

class OptionFactory:

    """

    A class for parsing command-line options and arguments to scripts.
    See below for example code that uses the OptionFactory.

    """
    
    def __init__(self):
        self.name = None
        self.__shortstring = 'h'
        self.__longlist = ['help']
        self.__options = [('help','h','help','','print this help message')]
        self.__args = 0
        self.__argdesc = None
        self.args = None
        self.__dict = {}

    def __getitem__(self, item):
        return self.__dict[item]

    def add_options(self, options):
        """

        'options' is a sequence of tuples of the form:
        (label, short, long, value, desc)

        label = identifier for the option, used to retrieve option value
                after parsing the command line
        short = short form of option, e.g. 'h'
        long  = long form of option, e.g. 'help'
        value = descriptive string of the value the option requires
        desc  = description of the option for the help message

        """
        for option in options: self.__add(option)

    def add_argdesc(self, argdesc):
        """ add a description of the expected arguments """
        self.__argdesc = argdesc

    def __add(self, option):
        self.__options.append(option)
        label, short, long, value, desc = option
        if short:
            self.__shortstring = self.__shortstring+short
            if value: self.__shortstring = self.__shortstring+':'
        if long:
            if value:
                self.__longlist.append(long+'=')
            else:
                self.__longlist.append(long)
        self.__dict[label] = 0

    def usage(self):
        if self.__options: optstr = ' [OPTION...]'
        else: optstr = ''
        usage = 'Usage: %s%s %s\n' % (self.name, optstr, self.__argdesc)
        if self.__options: usage = '%sOptions:\n' % usage
        for option in self.__options:
            label, short, long, value, desc = option
            if short: short = '-%s' % short
            if long: long = '--%s' % long
            if value:
                if short: sval = value
                else: sval = ''
                if long:
                    lval = value; vl = '='
                else:
                    lval = ''; vl = ''
            else:
                sval = ''; lval = ''; vs = ''; vl = ''
            if short and long: comma = ',  '
            else: comma = ''
            s = '  %s%s%s%s%s%s' % (short,sval,comma,long,vl,lval)
            s = ljust(s, 30)
            s = '%s%s\n' % (s, desc)
            usage = '%s%s' % (usage, s)
        return usage
        
    def parse(self, argv):
	""" pass in sys.argv, not sys.arv[1:] """

        self.name = argv[0]
        try:
            optlist, args = getopt(argv[1:], self.__shortstring, self.__longlist)
            for opt in optlist:
                self.__process_opt(opt)
            self.args = args
        except error, x:
            msg = 'Error parsing options:  %s' % x
            sys.stderr.write('%s\n' % msg)
            sys.stderr.write('\n%s\n' % self.usage())
            sys.exit(1)

    def __process_opt(self, opt):
        option, optval = opt
        if option in ('-h', '--help'):
            print self.usage()
            sys.exit(0)
        for item in self.__options:
            label, short, long, value, desc = item
            match = 0
            if option == '-%s' % short: match = 1
            elif option == '--%s' % long: match = 1

            if match:
                if optval and value:
                    entry = self.__dict.get(label)
                    if entry:
                        entry = [entry]
                        entry.append(optval)
                        self.__dict[label] = entry
                    else:
                        self.__dict[label] = optval
                else:
                    self.__dict[label] = 1

# Run this script with options to see the OptionFactory in action

if __name__ == '__main__':

    test_flag = 'test_flag'
    verbose_flag = 'verbose_flag'
    numreps = 'numreps'
    infilename = 'infilename'
    mystery_flag = 'mystery_flag'

    opts = [(test_flag,    't', 'test',      '',     'test option'),
            (verbose_flag, 'v', 'verbose',   '',     'verbose output'),
            (numreps,      'n', '',          '#',    'do it # times'),
            (infilename,   '',  'load-file', 'FILE', 'load FILE'),
            (mystery_flag, 'x', '',          '',     'mystery option with no long version')]

    of = OptionFactory()
    of.add_options(opts)
    of.add_argdesc('[file1 file2 ...]')
    of.parse(sys.argv)

    print 'test_flag:',    of[test_flag]
    print 'verbose_flag:', of[verbose_flag]
    print 'numreps:',      of[numreps]
    print 'infilename:',   of[infilename]
    print 'mystery_flag:', of[mystery_flag]
    print 'args:',         of.args





More information about the Python-list mailing list