Python Command Line Arguments
There is an excellent class for dealing with the boring task of treating command line arguments: OptionParser [1].
Following the tutorial made me do the following silly little program to test its features.
Features of Option Parser
The class can "automatically" generate text like options that are available:
>./parse_args --help [...] Options: --version show program's version number and exit -h, --help show this help message and exit -f FILE, --file=FILE FILE is name of infile (repeated use is ok). -o OUT, --out=OUT OUT is name of outfile (for non-default names) -n NUM Number of items from FILE to OUT to process. -v Enable printing of status messages to stdout. -q Disable printing of status messages to stdout.
Also a number of boring special cases and errors are dealt with automagically:
>./parse_args -f [...] parse_args: error: -f option requires an argument
While testing it I also found some limitations, it seems non-trivial to use one switch and then apply a bunch of arguments (without knowing how many) after it. (The documentation shows an example that "should" work but that does not.)
What I would like is something like this:
>./parse_args -f a.txt b.txt c.txt
Where a.txt, b.txt and c.txt are stored as infiles. I had to make an ugly hack to make it work.
Concrete example of the Python Option Parser
Below is my silly little program. It copies all or some ("-n 10" for ten) lines in all infiles and write them to an outfile. The switch -v enable verbosity and -q disables verbosity. Again the documentation is not perfect as I see it - I'd like an exception to be thrown when combining -v and -q but I did not manage to do that at the same time as -v and -q touch the same variable.
#!/usr/bin/python from optparse import OptionParser usage = """Usage: %prog [options] or %prog [filenames] [options] Defaults: OUT = 'out.txt'\n -q is on (-v is thus off) Note: All anonymous arguments will be treated as filenames Examples: %prog in1.txt in2.txt in1.txt and in2.txt wille be treated and stored in a.out %prog -f in.txt -n 10 -o out.txt The first 10 items in in.txt will be processed into out.txt """ parser = OptionParser(usage=usage, version="%prog 0.1") parser.add_option('-f', '--file', dest='infilenames', action='append', help='FILE is name of infile (repeated use is ok).', metavar='FILE') parser.add_option('-o', '--out', dest='outfilename', help='OUT is name of outfile (for non-default names)', metavar='OUT') parser.add_option('-n', dest='num', type='int', help='Number of items from FILE to OUT to process.') parser.add_option('-v', dest='verbose', action='store_true', help='Enable printing of status messages to stdout.') parser.add_option('-q', dest='verbose', action='store_false', default=False, help='Disable printing of status messages to stdout.') (options, args) = parser.parse_args() if args and not options.infilenames: options.infilenames = list() # anonymous arguments must be filenames while args: item = args.pop(0) options.infilenames.append(item) # open outfile if options.outfilename: o = open(options.outfilename, 'w') else: o = open('out.txt', 'w') # deal with infiles for item in options.infilenames: if options.verbose: print " dealing with %s" % item ctr = 0 f = file(item,'r') for line in f: # if -n break after a certain number of lines if options.num != None and ctr == options.num: break ctr += 1 o.write(line) f.close() if options.verbose: print " copied %d lines from %s to %s" % (ctr, f.name, o.name) o.close()
Conclusions
I am in love - I will never again use some ugly hack to fix command line options (I have done a number of such ugly hack...) !
This page belongs in Kategori Programmering.