Easy command line parsing? (Was Re: understanding sys.argv[])

Greg Ewing see_reply_address at something.invalid
Mon Aug 19 20:58:30 EDT 2002


Huaiyu Zhu wrote:

> Is there an existing module that allows simple operations like the
> following?
> 
>     from cmdline import parse_cmdline
>     args, kwargs = parse_cmdline()
>     func(*args, **kwargs)


I haven't heard of one, but I like this idea -- it's
the most Pythonic suggestion I've seen for this so
far!

In fact, it inspired me just now to write the module
attached below. I enhanced it a bit so that it
accepts a specification of which option letters
take arguments -- I hope Huaiyu will forgive me!

#-----------------------------------------------------------------
#
#  A Pythonically minimalistic command line parser
#  Inspired by ideas from Huaiyu Zhu
#  <huaiyu at gauss.almadan.ibm.com> and Robert Biddle
#  <Robert.Biddle at comp.vuw.ac.nz>.
#
#-----------------------------------------------------------------

class CommandLineError(Exception):
   pass

def clparse(switches, flags, argv = None):
   """clparse(switches, flags, argv = None)

   Parse command line arguments.

   switches = string of option characters not taking arguments
   flags = string of option characters taking an argument
   argv = command line to parse (including program name), defaults
          to sys.argv

   Returns (args, options) where:

   args = list of non-option arguments
   options = dictionary mapping switch character to number of
             occurrences of the switch, and flag character to
             list of arguments specified with that flag

   Arguments following "--" are regarded as non-option arguments
   even if they start with a hyphen.
   """
   if not argv:
     import sys
     argv = sys.argv
   argv = argv[1:]
   opts = {}
   args = []
   for c in switches:
     opts[c] = 0
   for c in flags:
     if c in switches:
       raise ValueError("'%c' both switch and flag" % c)
     opts[c] = []
   seen_dashdash = 0
   while argv:
     arg = argv.pop(0)
     if arg == "--":
       seen_dashdash = 1
     elif not seen_dashdash and arg.startswith("-"):
       for c in arg[1:]:
         if c in switches:
           opts[c] += 1
         elif c in flags:
           try:
             val = argv.pop(0)
           except IndexError:
             raise CommandLineError("Missing argument for option -%c" % c)
           opts[c].append(val)
         else:
           raise CommandLineError("Unknown option -%c" % c)
     else:
       args.append(arg)
   return args, opts

if __name__ == "__main__":
   def spam(args, a, b, c, x, y, z):
     print "a =", a
     print "b =", b
     print "c =", c
     print "x =", x
     print "y =", y
     print "z =", z
     print "args =", args
   args, kwds = clparse("abc", "xyz")
   spam(args, **kwds)

#-----------------------------------------------------------------

-- 
Greg Ewing, Computer Science Dept,
University of Canterbury,	
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg




More information about the Python-list mailing list