2

For some reason, I have non standard command line options for my program. My program takes in a long option also with a single '-'. For example, a valid command line option would be '-f' / '-foo'. Both short and long options need to have an argument separated by space or an '='.

I am trying to parse this using the optparse, but I understand that optparse does not support non GNU-standard options. Is there a way to tweak optparse to do this?

3
  • Note: Using optparse is discouraged since python version 2.7. The optparse module is deprecated and will not be developed further; development will continue with the argparse module. See [PEP 0389][1] for more info. [1]: python.org/dev/peps/pep-0389 Commented Apr 3, 2013 at 22:32
  • 1
    @shakaran: a little tip, you use [inline link format](http://example.com) (which appears as inline link format) in comments to make links. Commented Apr 3, 2013 at 22:49
  • Thanks! I will take that in next comment link. Unfortunately I cannot edit my last comment as far I know. Commented Apr 3, 2013 at 22:52

3 Answers 3

2

Here's a mildly hackish way to do what you need.

Subclass Option and OptionParser and patch some of the methods:

from optparse import Option, OptionError, OptionParser

class MyOption(Option):
    def _set_opt_strings(self, opts):
        for opt in opts:
            if len(opt) < 2:
                raise OptionError(
                    "invalid option string %r: "
                    "must be at least two characters long" % opt, self)
            elif len(opt) == 2:
                self._short_opts.append(opt)
            else:
                self._long_opts.append(opt)

class MyOptionParser(OptionParser):
    def _process_args(self, largs, rargs, values):
        while rargs:
            arg = rargs[0]
            if arg == "--":
                del rargs[0]
                return
            elif arg[0:2] == "--":
                self._process_long_opt(rargs, values)
            elif arg[:1] == "-" and len(arg) > 1:
                if len(arg) > 2:
                    self._process_long_opt(rargs, values)
                else:
                    self._process_short_opts(rargs, values)
            elif self.allow_interspersed_args:
                largs.append(arg)
                del rargs[0]
            else:
                return 

Now you can do

parser = MyOptionParser()
parser.add_option(MyOption("-f", "-file", dest="filename",
                 help="write report to FILE", metavar="FILE"))
parser.add_option(MyOption("-q", "-quiet",
                 action="store_false", dest="verbose", default=True,
                 help="don't print status messages to stdout"))

With this, parser will accept -file as an option (and will not accept e.g. -fq).

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks a lot. This actually helps me. However, when printing the help or if an invalid option is mentioned, it prints the -- option. To be clear. in your above code, if I gave the option as -fle in the command line, the error message would be: "no such option --fle". Where can I change this behavior, so that it prints it as " no such option: -fle"?
To do that, you'd need to patch Option. I've added the necessary patch to my answer.
I understand that this helps in setting the long option with a single - in the 'Option', so when it prints the help message it would print the option with single -. But the error message that displays for an invalid option is showing a double dash. For Ex: Consider the options you have mentioned above. In the command line if I give an option "-invalid" (an option that does not exist), it prints an error message "no such option --invalid" (this has double dash, but I gave a single dash in the command line). I don't understand how it is changing the cmd line argument to a double dash.
@user2242512: I updated the patch for OptionParser along with Option. Be sure you have the new code (I removed a line which converted - to -- as it was no longer necessary with the patched Option).
I kinda figured it out before I saw your reply, but 'Thanks a lot'. This fixes the problem I originally had.
|
1

From the optparse documentation

option:
an argument used to supply extra information to guide or customize the execution of a program. There are many different syntaxes for options; the traditional Unix syntax is a hyphen (“-”) followed by a single letter, e.g. -x or -F. Also, traditional Unix syntax allows multiple options to be merged into a single argument, e.g. -x -F is equivalent to -xF. The GNU project introduced -- followed by a series of hyphen-separated words, e.g. --file or --dry-run. These are the only two option syntaxes provided by optparse.

(emphasis added)

So no, you cannot specify other ways of handling arguments with optparse. You can, however, parse the arguments yourself by using argv from the sys module.

This is going to be more work, but it might look something like:

from sys import argv
for arg in argv:
    if arg.startswith("-") or arg.startswith("--"):
        # Parse the argument

1 Comment

Thanks for the reply. I already thought of this, but I was wondering if there was a way to do this using optparse. Right now, I am using parser.add_option to add a normal long option. I am then modifying the argv to append a - before the long options so that the optparse.OptionParser can parse it. For Ex: parser.add_option("--foo",dest="foo"). if the command line option is -foo, i would parse it and make it '--foo' and send it as an argument to the parser function. But the problem here is that in help it would print the option as --foo, but I want it as -foo. Can I change the help text?
0

I don't think there's any way to tweak optparse (though I don't know for certain), but getopt is your alternative that will handle C style command-line options.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.