Before anything else: what is argument parsing? It’s basically how we tell our programs which arguments to use when they run. For example, let’s say I have this program called “calculate_square”:
# This function calculates the square of a given number
def calculate_square(num): # Function definition with one parameter
"""
Calculates the square of a given number.
Parameters:
num (int or float): The number to be squared.
Returns:
int or float: The square of the given number.
"""
return num ** 2 # Returns the square of the given number
If you want to call it with the number `5`, you would do:
# This script calculates the square of a given number
# It takes in a number as an argument and prints the square of that number
# The first line is a shebang, which specifies the interpreter to be used to run the script
#!/bin/bash
# The next line is a comment, which explains the purpose of the script
# This script calculates the square of a given number
# The next line is a variable declaration, which stores the first argument passed to the script
# The variable is named "num" and it will hold the number whose square is to be calculated
num=$1
# The next line is a conditional statement, which checks if the variable "num" is empty
# If it is empty, the script will exit with an error message
if [ -z "$num" ]; then
echo "Please provide a number as an argument"
exit 1
fi
# The next line is a command substitution, which executes the command within the parentheses and stores the output in the variable "square"
# The command within the parentheses is a python script that calculates the square of the number stored in the variable "num"
square=$(python calculate_square.py $num)
# The next line is a print statement, which prints the square of the number
echo $square
But what if we wanted to add some options for verbosity or help? That’s where argument parsing comes in! We can use a library called argparse, which makes it super easy to handle all kinds of arguments and options. Here’s an example:
# Import the argparse library
import argparse
# Create an ArgumentParser object
parser = argparse.ArgumentParser()
# Add a positional argument "num" with type int
parser.add_argument("num", type=int)
# Add an optional argument "-v" or "--verbose" with action "count"
# This will count the number of times the argument is used
parser.add_argument("-v", "--verbose", action="count")
# Parse the arguments and store them in the "args" variable
args = parser.parse_args()
# Check if the "verbose" argument was used at least twice
if args.verbose >= 2:
# If yes, print the square of the number using the calculate_square function
print(f"The square of {args.num} is {calculate_square(args.num)}.")
# If the "verbose" argument was used only once
elif args.verbose == 1:
# Print the number and its square using the calculate_square function
print(f"{args.num}^2 == {calculate_square(args.num)}")
# If the "verbose" argument was not used at all
else:
# Simply print the square of the number using the calculate_square function
print(calculate_square(args.num))
Now, when you run the program with `-v` or `–verbose`, it will output more information based on how many times that argument was used (i.e., `-vv` would be twice as verbose). And if you add a `help` option, argparse will automatically generate some documentation for your program:
#!/bin/bash
# This script calculates the square of a given number and allows for different levels of verbosity.
# Define the usage message for the script.
usage() {
echo "Usage: $0 [-h] [--verbose {0,1,2}] num"
echo " -h, --help show this help message and exit"
echo " --verbose {0,1,2} increase output verbosity (default: 0)"
}
# Set default values for the optional arguments.
verbose=0
# Use the getopts function to parse the command line arguments.
# The colon after v indicates that the option requires an argument.
while getopts ":hv:" opt; do
case ${opt} in
h ) # If the help option is used, print the usage message and exit.
usage
exit 0
;;
v ) # If the verbose option is used, set the verbose level to the argument provided.
verbose=$OPTARG
;;
\? ) # If an invalid option is used, print the usage message and exit with an error.
echo "Invalid option: -$OPTARG" 1>&2
usage
exit 1
;;
esac
done
# Shift the command line arguments so that the positional argument is now $1.
shift $((OPTIND -1))
# Check if the positional argument is provided.
if [ -z "$1" ]; then
echo "Missing argument: num" 1>&2
usage
exit 1
fi
# Calculate the square of the given number.
square=$(( $1 * $1 ))
# Print the result based on the verbose level.
case $verbose in
0 ) # If the verbose level is 0, only print the result.
echo $square
;;
1 ) # If the verbose level is 1, print the result and a message indicating the verbosity level.
echo "The square of $1 is $square."
;;
2 ) # If the verbose level is 2, print the result, a message indicating the verbosity level, and the original number.
echo "The square of $1 is $square. (Verbose level: $verbose, Original number: $1)"
;;
esac
# Example usage:
# $ bash calculate_square.sh 5
# 25
# $ bash calculate_square.sh -v 1 5
# The square of 5 is 25.
# $ bash calculate_square.sh -v 2 5
# The square of 5 is 25. (Verbose level: 2, Original number: 5)
Pretty cool, right? And that’s just scratching the surface! With argparse, you can add all kinds of options for your program from simple flags to complex subcommands. So go ahead and start experimenting with argument parsing in Python it’ll make your programs more powerful (and less frustrating) than ever before!