Technology / Programming / Python
Python argparse - the Perl Getopt equivalent
Little known tricks in using Python argparse
I am a Perl expert. Hence, I have used Perl’s Getopt::Long module for ages.
Around 2 years back, my org decided to use Python. As I started developing tools & automation in Python, I wanted a Python module that provides similar functionality to Perl’s Getopt::Long.
Since I was looking for something similar, I found Python’s getopt module. But, it is very limited in its functionality and non-intuitive. Using it results in too much unnecessary code.
Thankfully, the documentation of getopt starts with a “note” asking the reader to consider argparse module. I am so glad that I gave attention to this note, which goes as follows:
NoteThe getopt module is a parser for command line options whose API is designed to be familiar to users of the C getopt() function. Users who are unfamiliar with the C getopt() function or who would like to write less code and get better help and error messages should consider using the argparse module instead.
Eventually Perl also came up with Getopt::ArgParser inspired by Python’s argparse. But that’s for a different article.
The documentation of argparse is very good. In fact, there are two documentations available:
- A gentle introduction to argparse: argparse tutorial
- API reference: argparse library
Going through the above two documentations in depth will certainly help one become very comfortable with the usage of Python’s argparse module.
At a high level you do 3 steps to parse your command line arguments:
- Create an ArgumentParser object.
- Add arguments to the object using add_argument() method.
- Parse the arguments through the parse_args() method.
To implement several different use cases of using command line arguments, argparse already provides a truck load of interesting options like these:
- Positional arguments
- Optional arguments
- Combining Positional & Optional arguments
- Short options & Long options
- Mutually exclusive options
- Simple usage/help message implementation
- Different types of values for the argument
- Different actions for the arguments
- Different number of values for arguments
- Different fixed choices as values for an argument
- Default value for an argument
- Etc…
The documentation links provided above explains these options in detail and hence I am not going to repeat it here.
But, every now and then comes an interesting use case which can’t be implemented in a straight forward way. We need to add some Python magic to accomplish these unique use cases.
Let me share few of these tricks that I learnt through my experience of using argparse. Most of these cannot be inferred easily from the documentation.
Case insensitive input
To convert the command line argument’s value to upper case, just mention the type as “str.upper”. You could even pass a callable (function) as the value for type. Then this callable will be called with the value as an argument.
Choices & default value for it
The scenario & the solution:
- Optional command line argument — hence
"--perform"
- Having a value from a set of choices — hence
choices=[“SING”, “ACT”, “DANCE”, “ALL”]
- If value is not provided (but command line argument is provided), then choose a default value of “ALL” — hence
nargs=’?’, const=’ALL’
Dependent command line arguments
Have you ever faced a scenario where one command line argument makes sense ONLY IF another command line argument is chosen?
Well, it is possible to implement it with the required parameter of add_argument() method.
In the below code snippet, if -d is chosen, then it is mandatory to choose -p option.
1 argument 3-in-1 values
Imagine a scenario where if an command line argument is not chosen then action 1 has to be performed, and if the argument is chosen but a value is not provided then action 2 has to be performed and finally if the argument is chosen and a value is provided then action 3 has to be performed.
For example, if -p is not chosen, then “Play instrumental”; if -p is chosen but a value is not provided, then “Play Backstreet Boys”; and if -p is chosen and a value is provided, then “Play <provided album>”.
The above example and the code snippet also explains the difference between const
& default
when nargs=’?’
.
What are the other interesting use cases that you have come across and what has been your solution for implementing the same?