Better Python Command Line Arguments with argparse

If you search for information on how to write Python modules that accepts command line arguments, you are very likely to stumble upon sys.argv and getopt() and go with it. But since Python 3.2 there is a better alternative that requires less boilerplate and less re-inventing the wheel: argparse.

Just like getopt() argparse relies on sys.argv but it is more high-level and provides more functionality out of the box. At the core of argparse is the class ArgumentParser, which returns an object that you can use to create the argument interface. This interface will automatically provide argument parsing and generate the help text that users expect when using -h or –help.

We will start with a simple program that accepts two positional arguments:

1
2
3
4
5
6
7
8
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("positional_argument_1")
parser.add_argument("positional_argument_2")
args = parser.parse_args()

print(args.positional_argument_1)

So first a ArgumentParser-object is created, which we then add two (requied) positional arguments to and finally we dispatch the parser. This will then look into sys.argv and figure out how to parse its contents (which is all arguments provided by the user).

That looks very neat and object-oriented. But we could instead access any positonal arguments directly through sys.argv with much less code:

1
2
3
4
import sys

print(sys.argv[1])
# note: 0 = the name of the script, first positional argument at 1

So what is the point of using argparser? Let’s look at a more functional example:

1
2
3
4
5
6
7
8
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--string", required=True,
	help="string to uppercase")
args = vars(parser.parse_args())
 
print(f"Uppercase of {args['string']} is {args['string'].upper()}")

Here we can see argparse starts to shine. This time we add an argument as a flag argument instead of positional. It is also set as required and a small help text is provided. This is what is returned if we run the script without any arguments:

usage: main.py [-h] -s STRING
main.py: error: the following arguments are required: -s/--string

So argparse will automatically make sure all required arguments are provided. And it also displays usage information on what arguments this program expects, something familiar to anyone who has used command line programs. If we provide only the -h flag futher information is shown:

usage: main.py [-h] -s STRING

optional arguments:
  -h, --help            show this help message and exit
  -s STRING, --string STRING
                        string to uppercase

This format should be even more familiar if you have played around on the command line. And argparse will automatically provide this help interface from the arguments that is specified, we did not have to set anything up ourselves!

So now we know how to use this program and if we provide -s andreas it will return:

Uppercase of andreas is ANDREAS

For this input sys.argv will contain either [‘main.py’, ‘-s’, ‘andreas’], or [‘main.py’, ‘–string’, ‘andreas’] if we had used the –string flag instead. But thanks to argparser we no longer have to parse this manually and can ignore all possible edge-cases and order.

This is just the basics and I plan to cover more advanced usage sometime. The docs has a more complete reference.

While argparser only handles arguments sent when starting the program, you can use python-prompt-toolkit to create more interactive command prompts.