views:

1053

answers:

5

What would be an easy expression to process command line arguments if I'm expecting anything like 001 or 999 (let's limit expectations to 001...999 range for this time), and few other arguments passed, and would like to ignore any unexpected?

I understand if for example I need to find out if "debug" was passed among parameters it'll be something like that:

if 'debug' in argv[1:]:
  print 'Will be running in debug mode.'

How to find out if 009 or 575 was passed?

All those are expected calls:

python script.py
python script.py 011
python script.py 256 debug
python script.py 391 xls
python script.py 999 debug pdf

At this point I don't care about calls like that:

python script.py 001 002 245 568
python script.py some unexpected argument
python script.py 0001
python script.py 02

...first one - because of more than one "numeric" argument; second - because of... well, unexpected arguments; third and fourth - because of non-3-digits arguments.

+14  A: 

Have a look at the optparse module. Dealing with sys.argv yourself is fine for really simple stuff, but it gets out of hand quickly.

Note that you may find optparse easier to use if you can change your argument format a little; e.g. replace debug with --debug and xls with --xls or --output=xls.

John Fouhy
I'm not sure this is worth it when the OP is just using arguments, not options.
Nikhil Chelliah
+2  A: 

optparse is your best friend for parsing the command line. Also look into argparse; it's not in the standard library, though.

regan
+13  A: 

As others answered, optparse is the best option, but if you just want quick code try something like this:

import sys, re

first_re = re.compile(r'^\d{3}$')

if len(sys.argv) > 1:

    if first_re.match(sys.argv[1]):
        print "Primary argument is : ", sys.argv[1]
    else:
        raise ValueError("First argument should be ...")

    args = sys.argv[2:]

else:

    args = ()

# ... anywhere in code ...

if 'debug' in args:
    print 'debug flag'

if 'xls' in args:
    print 'xls flag'

EDIT: Here's an optparse example because so many people are answering optparse without really explaining why, or explaining what you have to change to make it work.

The primary reason to use optparse is it gives you more flexibility for expansion later, and gives you more flexibility on the command line. In other words, your options can appear in any order and usage messages are generated automatically. However to make it work with optparse you need to change your specifications to put '-' or '--' in front of the optional arguments and you need to allow all the arguments to be in any order.

So here's an example using optparse:

import sys, re, optparse

first_re = re.compile(r'^\d{3}$')

parser = optparse.OptionParser()
parser.set_defaults(debug=False,xls=False)
parser.add_option('--debug', action='store_true', dest='debug')
parser.add_option('--xls', action='store_true', dest='xls')
(options, args) = parser.parse_args()

if len(args) == 1:
    if first_re.match(args[0]):
        print "Primary argument is : ", args[0]
    else:
        raise ValueError("First argument should be ...")
elif len(args) > 1:
    raise ValueError("Too many command line arguments")

if options.debug:
    print 'debug flag'

if options.xls:
    print 'xls flag'

The differences here with optparse and your spec is that now you can have command lines like:

python script.py --debug --xls 001

and you can easily add new options by calling parser.add_option()

Van Gale
+2  A: 

If you want to implement actual command line switches, give getopt a look. It's incredibly simple to use, too.

sli
I wouldn't say getopt is all that simple - sure, it's better than doing the parsing manually, but it's just a port of some C code that doesn't really take advantage of Python's strengths. I'd almost always recommend optparse over getopt.
David Zaslavsky
A: 

Van Gale is largely correct in using the regular expression against the argument. However, it is NOT absolutely necessary to make everything an option when using optparse, which splits sys.argv into options and arguments, based on whether a "-" or "--" is in front or not. Some example code to go through just the arguments:

import sys
import optparse

claParser = optparse.OptionParser()
claParser.add_option(
(opts, args) = claParser.parse_args()
if (len(args) >= 1):
  print "Arguments:"
  for arg in args:
    print "  " + arg
else:
  print "No arguments"
sys.exit(0)

Yes, the args array is parsed much the same way as sys.argv would be, but the ability to easily add options if needed has been added. For more about optparse, check out the relevant Python doc.

PTBNL