0

I'm writing a script that acts as a proxy for a plugin class's run method.

The script would be invoked like this:

> main.py -v --plugin=Foo --extra=bar -c

The result of this command would be the equivalent of:

plugin = my.module.Foo()
plugin.run(extra='bar', c=True)

Note that anything in front of --plugin is used internally by main.py and not passed to the plugin. Anything after --plugin is ignored by main.py and instead passed directly to the plugin.

The problem I'm running into is that I can't find a getopt-like class that will allow me to parse argv without having to specify a list of allowed options.

I'd prefer not to have to rewrite getopt with one line commented out. Are there any better options out there?

  • Similar to http://stackoverflow.com/questions/3002062/how-can-i-allow-undefined-options-when-parsing-args-with-getopt, but for Python instead of Perl. –  Jul 27 '11 at 23:22

5 Answers5

3

What you want is in the argparse library, see http://docs.python.org/dev/library/argparse.html#partial-parsing:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
>>> parser.add_argument('bar')
>>> parser.parse_known_args(['--foo', '--badger', 'BAR', 'spam'])
(Namespace(bar='BAR', foo=True), ['--badger', 'spam'])
agf
  • 171,228
  • 44
  • 289
  • 238
  • I don't think this is what the OP is looking for. This gets the known (pre-specified) arguments, where what is desired is getting long options without having to specify what they are first. – Keith Jul 28 '11 at 01:48
  • 1
    Any options it doesn't recognize will end up in the list in the second position in the tuple -- above, `badger` and `spam` aren't pre-specified. This list can just be passed to the plugin. – agf Jul 28 '11 at 01:51
0

You can do something silly and just generate a dictionary from which you can look up keys and the like to determine what to do with each item...

#!/usr/bin/python
import sys 
options = dict()
for pair in map(lambda item: item.lstrip('-'), sys.argv[1:]):
    pair = pair.split('=')
    if len(pair) < 2:
        option, val = pair[0], True
    else:
        option, val = pair
    options[option] = val 
print options
sampwing
  • 1,238
  • 1
  • 10
  • 13
0

You're in luck. I wrote a modified getopt that does exactly that. One limitition, however, is that short options must precede long options. That may be fixable.

Keith
  • 42,110
  • 11
  • 57
  • 76
0

I just discovered that getopt will stop parsing if it encounters --:

Python 2.6.6 (r266:84292, Jun 16 2011, 16:59:16) 
Type "help", "copyright", "credits" or "license" for more information.
>>> from getopt import getopt
>>>
>>> argv = ['-v', '--plugin=foo', '--', '--extra=bar', '-c']
>>> opts, extra = getopt(argv, 'v', 'plugin=')
>>>
>>> opts
[('-v', ''), ('--plugin', 'foo')]
>>>
>>> extra
['--extra=bar', '-c']

Note that the above argv is the equivalent of calling:

> main.py -v --plugin=Foo -- --extra=bar -c

I like this solution particularly since it gives the user a little extra flexibility in how he wants to order the parameters.

-1

Use a regular expression to search for 'plugin=, and if found, split the line and use getopt to parse each half.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153