Processing multiple values for one single option using getopt/optparse?

Open Grieves picture Open Grieves · Nov 5, 2010 · Viewed 34.9k times · Source

Is it possible to fetch multiple values for one option using getopt or optparse, as shown in the example below:

./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7

Please note that the number of actual values for each option (-c, -b) could be either 1 or 100. I do not want to use: ./hello_world -c "arg1 arg2 arg3" -b "arg4 arg5 arg6 arg7"

It seems to me that this may not be possible (and perhaps in violation of POSIX), please correct me if I'm wrong.

I've seen examples where all the non-options at the end of the line (./hello_world -c arg1 -b arg1 arg2 arg3) can be gathered... but not for the first of multiple option.

I'd like my app to work on a wide range of platforms with different Python versions, so I've not looked at argparser.

Answer

Richard Gomes picture Richard Gomes · May 1, 2012

Yes, it can be done with optparse.

This is an example:

./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3

which prints:

arguments: ['arg1', 'arg2', 'arg3']
options: {'categories': ['aaa', 'bbb', 'ccc']}

Full working example below:

#!/usr/bin/env python

import os, sys
from optparse import OptionParser
from optparse import Option, OptionValueError

VERSION = '0.9.4'

class MultipleOption(Option):
    ACTIONS = Option.ACTIONS + ("extend",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)

    def take_action(self, action, dest, opt, value, values, parser):
        if action == "extend":
            values.ensure_value(dest, []).append(value)
        else:
            Option.take_action(self, action, dest, opt, value, values, parser)


def main():
    PROG = os.path.basename(os.path.splitext(__file__)[0])
    long_commands = ('categories')
    short_commands = {'cat':'categories'}
    description = """Just a test"""
    parser = OptionParser(option_class=MultipleOption,
                          usage='usage: %prog [OPTIONS] COMMAND [BLOG_FILE]',
                          version='%s %s' % (PROG, VERSION),
                          description=description)
    parser.add_option('-c', '--categories', 
                      action="extend", type="string",
                      dest='categories', 
                      metavar='CATEGORIES', 
                      help='comma separated list of post categories')

    if len(sys.argv) == 1:
        parser.parse_args(['--help'])

    OPTIONS, args = parser.parse_args()
    print "arguments:", args
    print "options:", OPTIONS

if __name__ == '__main__':
    main()

More information at http://docs.python.org/library/optparse.html#adding-new-actions