0

I have the following Python code that has 1 command line optional parameter (c) that has an argument and 2 options (a and b) that do not have an argument:

import sys, getopt

def main(argv):
   inputfile = ''
   outputfile = ''
   try:
      opts, args = getopt.getopt(argv,"abc:",["csvfile="])
   except getopt.GetoptError:
      print 'Error in usage - a does not require an argument'
      sys.exit(2)
   for opt, arg in opts:
      print "Raw input is: {}" .format(opt)
      if opt in ("-c", "--csvfile"):
         outputfile = arg
         print 'Output file is {}' .format(outputfile)
      elif opt == '-a':
         print 'Alpha'
      elif opt == '-b':
         print 'Beta'
      print 'User choice is {}' .format(opt.lstrip('-'))

if __name__ == "__main__":
   main(sys.argv[1:])

When I enter python readwritestore.py -a I get:

Raw input is: -a
Alpha
User choice is a

This is what I was hoping for if the commandline argument is -a. However, if I enter python readwritestore.py -a csvfile_name, then I get:

Raw input is: -a
Alpha
User choice is a

This is not what I intended for. In this function, c is the only option that rquires an argument. If I enter a with an argument, the code should give the error message that I set up

Error in usage - a does not require an argument

This does not happen for a or b. It is allowing the argument to be entered without raising an error.

If the options that do not require an argument are entered with an argument, then I would like it to raise an error. python readwritestore.py -a text and python readwritestore.py -b text should raise the error Error in usage - a does not require an argument.

Is there a way to specify this? Is getopt() the correct way to do this?

Additional Information:

I only want python readwritestore.py -c text to work with the argument. For the other 2 options, a and b, the code should raise the error.

edesz
  • 11,756
  • 22
  • 75
  • 123
  • 1
    You might want to consider [`argparse`](https://docs.python.org/3/library/argparse.html), Python's more intuitive module for this. – Scott Stevens Jul 20 '16 at 14:20
  • I have a lot of issue managing argument for script without a lib. But with [Argparse](https://docs.python.org/2/howto/argparse.html) this is really easy. I can post an anwser using this lib if you want. – pwnsauce Jul 20 '16 at 14:21
  • Was going to suggest the same, if you have no problems changing, give argparse a shot – Samuel Jul 20 '16 at 14:22

1 Answers1

1

checking the size of sys.argv (the list of argument supplied when calling the script) can help you checking that :

import sys
import getopt


def main(argv):
    inputfile = ''
    outputfile = ''
    opts, args = getopt.getopt(argv, "abc:", ["csvfile="])
    for opt, arg in opts:
        print "Raw input is:", opt
        if opt in ("-c", "--csvfile"):
            outputfile = arg
            print 'Output file is ', outputfile
        elif opt == '-a':
            if len(sys.argv)=2:
                print 'Alpha'
            else:
                print "incorect number of argument"
        elif opt == '-b':
            if len(sys.argv)=2:
                print 'Beta'
            else:
                print "incorect number of argument"
        print 'User choice is ', opt

if __name__ == "__main__":
    main(sys.argv[1:])

I know it's not what you asked (argparse) but here is how you could do it with argparse :

from argparse import *

def main():
    parser = ArgumentParser()
    parser.add_argument('-c', '--csvfile', help='do smth with cvsfile')
    parser.add_argument(
        '-a', '--Alpha', help='Alpha', action='store_true')
    parser.add_argument(
        '-b', '--Beta', help='beta smth', action='store_true')
    if args.csvfile:
        print 'Output file is {}' .format(args.csvfile)
    if args.Alpha:
        print 'Alpha'
    if args.Beta:
        print 'Beta'

if __name__ == "__main__":
    main()

It will raise an error is to many argument are supplied. (also python readwritestore.py -h will display the help just like man in unix)

pwnsauce
  • 416
  • 4
  • 14
  • That's exactly the mistake I made! Thanks for catching it. But `argparse` seems a lot better. I'll have to look into this. Thanks for the suggestion. – edesz Jul 20 '16 at 17:23
  • Sorry, I just wanted to ask a followup question. `argparse` looks really good - I am having trouble finding beginner's level tutorials for it - is there a good one that can be recommended for this? – edesz Jul 20 '16 at 20:03
  • @WR I understand you, the first time you use it it seems messed up. To learn it, i just copy-pasted exemple from there Doc, and tried to test value and tried to understand what appends. here is the tiniest exemple i satrted with : [SO exemple](http://stackoverflow.com/questions/7427101/dead-simple-argparse-example-wanted-1-argument-3-results) – pwnsauce Jul 21 '16 at 07:23
  • @WR the thing you have to focus on are : `action=` and `nargs=`. And at first, don't look into subparser – pwnsauce Jul 21 '16 at 08:32
  • Thanks. That will get me going. I seem to have some understanding of `nargs=`...need to really focus on `action=`. Appreciate the help. – edesz Jul 21 '16 at 15:24
  • 1
    @WR I stumbled upon that today : http://null-byte.wonderhowto.com/how-to/train-your-python-part-23-argparse-module-0170874/ – pwnsauce Jul 26 '16 at 07:54