Like many of you, I write a lot of throwaway scripts to do a task. These are quick undocumented 20-line blobs of code that do janitorial or maintenance tasks and they’re deleted almost as soon as they’re written.
But if something is going to endure, I try to take a more professional approach: documentation and comments, logging, checking sub-command errors, failing gracefully – and handling command-line arguments.
In fact, I’ve found that whether a script handles command-line arguments or not often determines if it’s permanent code or throwaway. Something designed to do one thing once has no need of configuration knobs, while code that can work many different ways often means we have a durable tool.
In this article, I’d like to show you how to use python’s very cool argparse module. If you’re coming from a shell/perl background, you’ll find it’s a little different than typical getopts. It’s more like Golang or other “big” language parsing.
In this case, we’re going to write some code with these options:
- -f will specify a file we’re going to process
- -v will turn on verbose (debugging) output
As you’ll see, Python will automagically include help output (-h).
Let’s look at some simple code. Python 2 is now obsolete and we’re going to using Python 3. Here is how we might implement the above requirements
I’ve stored the following in gronkulator.py (a suitable nonsense word that is used in everything from technical documentation to TV shows):
#!/usr/bin/python3 import argparse import os import sys def debug(message): if args.wants_debug: print (message) parser = argparse.ArgumentParser ( description = 'reciprocating trans-quantum gronkulator' ) parser.add_argument('-f', help="file to process", dest="file_name", action='store', required=True) parser.add_argument('-v', help="enable debugging", dest="wants_debug", action='store_true', required=False, default=False) args = parser.parse_args() debug ("Debugging output turned on") if os.path.exists(args.file_name) == False: print ("Error! File '%s' does not exist - aborting" % ( args.file_name )) sys.exit(1) print ("Processing file '%s'" % ( args.file_name ))
I’ve wrapped a few lines to make things easy to understand. Let’s do a quick walkthrough.
parser = argparse.ArgumentParser ( description = 'reciprocating trans-quantum gronkulator' )
This creates our parser object. BTW, you can parse the command-line arguments as many times as you want, so don’t be afraid to include argparse deep in some subroutine if you want to parse again locally.
parser.add_argument('-f', help="file to process", dest="file_name", action='store', required=True) parser.add_argument('-v', help="enable debugging", dest="wants_debug", action='store_true', required=False, default=False)
Here we add the arguments. Just reading the code you can probably figure it out. -f specifies the file name we’re going to work with. This parameter is required (=True) and the action is to “store” it in a the variable “args.file_name” (see below).
The next line adds the -v argument. This is optional and if set, it sets the variable “args.wants_debug” to True, otherwise it is set to False. This is very pleasant. After that line, you know the args.wants_debug variable is guaranteed to exist with teh right value and you can reference it anywhere.
args = parser.parse_args()
And this does the actual argument-parsing. The ‘args’ variable created will then have values that correspond to the “dest” variables (so args.file_name, args.wants_debug, etc.)
After this, we exercise the debug() function and then test to see if file_name exists. If not, we error out, otherwise we do whatever we need to do with it.
Let’s try the code:
# ./gronkulator.py usage: gronkulator.py [-h] -f FILE_NAME [-v] gronkulator.py: error: the following arguments are required: -f
So note that we wrote none of the “usage” code – it’s all generated by python. Let’s try with -h:
# ./gronkulator.py -h usage: gronkulator.py [-h] -f FILE_NAME [-v] reciprocating trans-quantum gronkulator optional arguments: -h, --help show this help message and exit -f FILE_NAME file to process -v enable debugging
Nice. Python has given us a complete help chart.
# ./gronkulator.py -f /tmp/junk Processing file '/tmp/junk' # ./gronkulator.py -v -f /tmp/junk Debugging output turned on Processing file '/tmp/junk'
Appears to be working as intended. We get debugging output if we turn on -v and don’t get it if we don’t, and the script picks up the -f argument.
There is a ton more you can do – everything from adding abbreviations and long-flags to adding epilog to help, parsing non-sys.argv streams, handling variables that are already-set, and so much more. Indeed, the main problem is that argparse itself has so many options that some readers are overwhelmed. But I think the basics – require some flags, access their values later – is very simple and easy to copy-paste from a recipe like the above. Enjoy!
Related Posts:
- One Week From Tomorrow…THE WORLD WILL LOSE THEIR MINDS!Lines Are Already Forming! - November 21, 2024
- Crunchbits Discontinuing Popular Annual Plans – The Community Mourns! - November 20, 2024
- RackNerd’s Black Friday 2024: Bigger, Better, and Now in Dublin! - November 19, 2024
Leave a Reply