Optik: Basic Usage

While Optik is quite flexible and powerful, you don't have to jump through hoops or read reams of documentation to get started. This document aims to demonstrate some simple usage patterns that will get you started using Optik in your scripts.

To parse a command line with Optik, you must create an OptionParser instance and define some options. You'll have to import the OptionParser classes in any script that uses Optik:

from optik import OptionParser

Early on in the main program, create a parser:

parser = OptionParser()

Then you can start defining options. The basic syntax is:

parser.add_option(opt_str, ...,
                  attr=value, ...)

That is, each option has one or more option strings, such as "-f" or "--file", and several option attributes that tell Optik what to expect and what to do when it encounters that option on the command line.

Typically, each option will have one short option string and one long option string, e.g.:

parser.add_option("-f", "--file", ...)

You're free to define as many short option strings and as many long option strings as you like, as long as there is at least one option string overall.

Once all of your options are defined, instruct Optik to parse your program's command line:

(options, args) = parser.parse_args()

(You can pass an argument list to parse_args() if you like, but that's rarely necessary: by default it uses sys.argv[1:].)

parse_args() returns two values:

This tutorial document only covers the four most important option attributes: action, type, dest (destination), and help. Of these, action is the most fundamental.

Option actions

Actions tell Optik what to do when it encounters an option on the command line. There is a fixed set of actions hard-coded into Optik; adding new actions is an advanced topic covered in Extending Optik. Most actions tell Optik to store a value in some variable -- for example, take a string from the command line and store it in an attribute of options.

If you don't specify an option action, Optik defaults to store.

The store action

The most common option action is store, which tells Optik to take the next argument (or the remainder of the current argument), ensure that it is of the correct type, and store it to your chosen destination.

For example:

parser.add_option("-f", "--file",
                  action="store", type="string", dest="filename")

Now let's make up a fake command line and ask Optik to parse it:

args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)

When Optik sees the "-f", it consumes the next argument, "foo.txt", and stores it in options.filename, where options is the first return value from parse_args(). So, after this call to parse_args(), options.filename is "foo.txt".

Some other option types supported by Optik are int and float. Here's an option that expects an integer argument:

parser.add_option("-n", type="int", dest="num")

Note that I didn't supply a long option, which is perfectly acceptable. I also didn't specify the action, since the default is store.

Let's parse another fake command-line. This time, we'll jam the option argument right up against the option -- "-n42" (one argument) is equivalent to "-n 42" (two arguments).

(options, args) = parser.parse_args(["-n42"])
print options.num

will print "42".

Trying out the float type is left as an exercise for the reader.

If you don't specify a type, Optik assumes string. Combined with the fact that the default action is store, that means our first example can be a lot shorter:

parser.add_option("-f", "--file", dest="filename")

If you don't supply a destination, Optik figures out a sensible default from the option strings: if the first long option string is "--foo-bar", then the default destination is foo_bar. If there are no long option strings, Optik looks at the first short option: the default destination for "-f" is f.

Adding types is covered in "Extending Optik".

Handling flag (boolean) options

Flag options -- set a variable to true or false when a particular option is seen -- are quite common. Optik supports them with two separate actions, store_true and store_false. For example, you might have a verbose flag that is turned on with "-v" and off with "-q":

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")

Here we have two different options with the same destination, which is perfectly OK. (It just means you have to be a bit careful when setting default values -- see Default values, below.)

When Optik sees "-v" on the command line, it sets the verbose attribute of the special "option values" object to a true value; when it sees "-q", it sets verbose to a false value.

Other actions

Some other actions supported by Optik are:

store_const
store a constant value
append
append this option's argument to a list
count
increment a counter by one
callback
call a specified function

These are covered in the Advanced Usage and Option Callbacks documents.

Default values

All of the above examples involve setting some variable (the "destination") when certain command-line options are seen. What happens if those options are never seen? Since we didn't supply any defaults, they are all set to None. Usually, this is just fine, but sometimes you want more control. To address that need, Optik lets you supply a default value for each destination, which is assigned before the command-line is parsed.

First, consider the verbose/quiet example. If we want Optik to set verbose to True unless "-q" is seen, then we can do this:

parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")

Oddly enough, this is exactly equivalent:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)

Those are equivalent because you're supplying a default value for the option's destination, and these two options happen to have the same destination (the verbose variable).

Consider this:

parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)

Again, the default value for verbose will be True: the last default value supplied for any particular destination attribute is the one that counts.

A clearer way to specify default values is the set_defaults() method of OptionParser, which you can call at any time before calling parse_args():

parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()

As before, the last value specified for a given option destination is the one that counts. For clarity, try to use one method or the other of setting default values, not both.

Generating help

There is one more feature that you will use in every script: Optik's ability to generate help messages. All you have to do is supply a help value for each option. Let's create a new parser and populate it with user-friendly (documented) options:

usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
                  action="store_true", dest="verbose", default=1,
                  help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", 
                  help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
                  metavar="FILE", help="write output to FILE"),
parser.add_option("-m", "--mode",
                  default="intermediate",
                  help="interaction mode: one of 'novice', "
                       "'intermediate' [default], 'expert'")

If Optik encounters either "-h" or "--help" on the command-line, or if you just call parser.print_help(), it prints the following to stdout:

usage: <yourscript> [options] arg1 arg2

options:
  -h, --help           show this help message and exit
  -v, --verbose        make lots of noise [default]
  -q, --quiet          be vewwy quiet (I'm hunting wabbits)
  -fFILE, --filename=FILE
                       write output to FILE
  -mMODE, --mode=MODE  interaction mode: one of 'novice', 'intermediate'
                       [default], 'expert'

There's a lot going on here to help Optik generate the best possible help message:

Error-handling

The one thing you need to know for basic usage is how Optik behaves when it encounters an error on the command-line -- e.g. "-n4x" where the "-n" option takes an integer. Optik prints your usage message to stderr, followed by a useful and human-readable error message. Then it terminates with a non-zero exit status by calling sys.exit().

If you don't like this, subclass OptionParser and override the error() method. See Extending Optik.

Putting it all together

Here's what my Optik-based scripts usually look like:

from optik import OptionParser

[...]

def main():
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage)
    parser.add_option("-f", "--file", type="string", dest="filename",
                      help="read data from FILENAME")
    parser.add_option("-v", "--verbose",
                      action="store_true", dest="verbose")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose")
    [... more options ...]

    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("incorrect number of arguments")

    if options.verbose:
        print "reading %s..." % options.filename

    [... go to work ...]


if __name__ == "__main__":
    main()