views:

391

answers:

4

Thank you for quack in pointing out the off-by-one!

The following code is my first attempt in writing code with Optparse.

How can you fix the following bug in getting the help by Optparse?

#!/usr/bin/env python
import sys
import os
from optparse import OptionParser


e = sys.argv[1]
b = sys.argv[2]
no = sys.argv[3]

def set_figu(figu):
        sum = 777
        return sum


def main():
        usage = "Usage: negative_bin_base.py <eksponentti> <siirre> <figu>"
        parser = OptionParser(usage)
        parser.add_option("-h", "--help", dest="help",
                        help="get synopsis of parameters")
        # print the output of the work-horse
        print set_figu(no)

        (options, args) = parser.parse_args()
        if len(args) < 4:
                parser.error("incorrect number of arguments")
        if options.informative:
                print "reading %s..." % options.help

if __name__ == "__main__":
        main()

Example of wrong output with correct number of parameters

python negative_bin_base.py 13 13 332
Traceback (most recent call last):
  File "negative_bin_base.py", line 37, in <module>
    main()
  File "negative_bin_base.py", line 26, in main
    help="get synopsis of parameters")
  File "/usr/lib/python2.6/optparse.py", line 1020, in add_option
    self._check_conflict(option)
  File "/usr/lib/python2.6/optparse.py", line 995, in _check_conflict
    option)
optparse.OptionConflictError: option -h/--help: conflicting option string(s): -h, --help
+6  A: 

The bug is that your arguments array includes the name of the script as sys.argv[0]. Thus your if is off-by-one:

# python sys.argv[0] sys.argv[1] sys.argv[2] sys.argv[3]
if len(sys.argv) < 4:
        sys.exit(usage)
quack quixote
+4  A: 

Constructor for class optparse.OptionParser(...) has optional named parameter 'add_help_option', which defaults to 'True'. You will have to explicitly reject default help option and message, if you want to provide your own.

parser = OptionParser(usage, add_help_option=False)

artdanil
if you find 'optparse' too much for what you need, you might also look into 'getopt' http://docs.python.org/library/getopt.html
artdanil
I was just posting a similar response. Thanks for this.
jathanism
+1  A: 

This should do what you require, based on your example above:

#!/usr/bin/env python
from optparse import OptionParser

def main():
    usage = "Usage: negative_bin_base.py <eksponentti> <siirre> <figu>"
    parser = OptionParser(usage)
    (options, args) = parser.parse_args()
    if len(args) != 3:
        parser.error("incorrect number of arguments")
    e = args[0]
    b = args[1]
    no = args[2]
    # ...

if __name__ == "__main__":
    main()
John Keyes
+1  A: 

For using optparse here's what I normally do:

  1. separate command line parsing from your main code base for better modularization. (Put the processing right after "if __name__ == "__main__"")

  2. Let optparse handle your help. (Use parser.print_help())

  3. Use the optparse constructs, if you don't like them just parse sys.argv yourself. (use add_option to define your necessary options)

Here's how I would write your sample using the optparse library:

def main():
    print 'Welcome to the main event!'


if __name__ == '__main__':
    import optparse
    parser = optparse.OptionParser()
    parser.add_option("-e", "--eksponentti", dest="eksponentti",
                      help="This is help for <eksponentti>.",
                      default=None)
    parser.add_option("-s", "--siirre", dest="siirre",
                      help="This is help for <siirre>.",
                      default=None)
    parser.add_option("-f", "--figu", dest="figu",
                      help="This is help for <figu>.",
                      default=None)

    (options, args) = parser.parse_args()
    if options.eksponentti and options.siirre and options.figu:
        main()
    else:
        print "ERROR -- Expected Arguments not given!"
        parser.print_help()

Running this without the necessary options will give the following output: (It's a little prettier than I can format it here...)

ERROR -- Expected Arguments not given! Usage: parm.py [options]

Options:   
    -h, --help            show this help message and exit   
    -e EKSPONENTTI, --eksponentti=EKSPONENTTI This is help for <eksponentti>.   
    -s SIIRRE, --siirre=SIIRRE This is help for <siirre>.   
    -f FIGU, --figu=FIGU  This is help for <figu>.
monkut
How do you read this line ` if options.eksponentti and options.siirre and options.figu:`? I am using 3 parameteters in my command and the if-clause is not true.
Masi
monkut has changed how your command line options are handled, he has named the options for you. For example, `python negative_bin_base.py -e 13 -s 13 -f 332`.
John Keyes
Thanks, john. Yes, options.<option> is where items created with 'add_option' are accessed. Using the 'add_option' command I'm creating an option and defaulting it to None. This will evaluate to 'False' in the if-clause. So if all the options are not provided you will see the error message and 'help' will be displayed.
monkut