This lesson is in the early stages of development (Alpha version)

Parsing Command Line Arguments

Overview

Teaching: 20 min
Exercises: 10 min
Questions
  • How can I access arguments passed to my Python script at runtime?

  • How can I create a sophisticated command line interface for my script?

  • How can I provide the user with more information about how to run my code?

Objectives
  • access command line arguments with sys.argv.

  • parse and use arguments and options with argparse.

  • create a comprehensive usage statement for their script.

It’s common for our scripts to require some information be provided by the user. The most common example of this is probably where a program requires the path/name of at least one input file on which to operate. Anyone who’s ever started editing their script to point hard-coded paths at a new set of input data has concluded that there must be a better way. And indeed there is: by writing our programs in such a way that they can adapt to and operate on whichever input they’re given (within reason!), we’re saving ourselves a lot of time in the long run. Setting up your program to adapt to user input and to provide that user with information about the expected usage/different arguments and options of the software is also a big step towards making your code appear professional and ready for use by others.

In this section, we’ll explore two options available in the standard library for handling information provided by the user to our program as part of the command line used to execute the script.

Simple Command Line Argument Access with sys.argv

The argv object within the sys module provides a very simple way of accessing the information on the command line: argv is the list that would be returned if the command used to run the program was split by whitespace:

$ cat argv_example1.py
from sys import argv

print('START')
print(argv)
for arg in argv:
    print(arg)
print('END')
$ python argv_example1.py one 2 3.0 four,five
START
['code/argv_example1.py', 'one', '2', '3.0', 'four,five']
code/argv_example1.py
one
2
3.0
four,five
END

Note about Bash code blocks: we include $ to represent the shell prompt in commands like those above (cat argv_example.py & python argv_example1.py one 2 3.0 four,five). When reproducing these commands on your own system, you should leave that extra $ symbol out.

4.1. Carry the Zero

  • What does sys.argv[0] return when you run it in a script?
  • What about in a Jupyter Notebook?
  • In what circumstances might this be useful?
  • Is the full path included in the returned value?
    • If not, take a look at the documentation for os and pathlib, other modules in the standard library, to find another function that could get this for you.

Solution

sys.argv[0] carries the name of the program that was run. In Jupyter, this has a rather cryptic value, showing the name of the program that was run to launch the Jupyter session. This probably isn’t useful in Jupyter, but in a standalone script or a module it can be helpful, e.g. for including in logging messages created by functions that could be imported into other programs.

Whether the full path to the program is included or not depends on the operating system. If you need to rely on the full path being available, it’s a safer bet to work with one of the other modules linked above.

One important thing to note about sys.argv is that all the values within the list are strings. If you want to use any of the arguments as integers etc, you’ll need to explicitly convert them within the body of your program.

$ cat argv_example2.py
from sys import argv

print('START')
for arg in argv[1:]:
    print(arg + 3)
print('END')
$ python argv_example2.py 1 2 3
START
Traceback (most recent call last):
  File "argv_example2.py", line 5, in <module>
    print(arg + 3)
TypeError: can only concatenate str (not "int") to str

4.2. Options & Arguments

The code block below shows the start of a program that takes three input files and returns either the product, the sum, or the mean, of the values given somewhere within them. (The details of how the files are processed and the returned values calculated are not shown.)

Fill in the blanks in the code (indicated with ___), so that the program can take an option, --output=output.csv, to specify an output file, or write to STDOUT otherwise. (Note: sys.stdout is an object representing the STDOUT stream.)

from sys import argv, stdout
from numpy import prod # use math.prod here if you're running Python 3.8
from statistics import mean

input_files = argv[-3:]

modes = {'--sum': sum,
         '--product': prod,
         '--mean': mean}
output_file = ___

for option in argv[___:-3]:
    if option in modes:
        output_function=modes[option]
    elif ___:
        output_file = option.split___

Once you’ve done this, try to change the code so that the program can take an arbitrary number of input files.

Look at the code again. Do you think this is a good way to construct an interface for a program like this? What potential problems can you identify with this approach? Pair up and discuss with a partner.

Solution

from sys import argv, stdout
from numpy import prod # use math.prod here if you're running Python 3.8
from statistics import mean

input_files = argv[-3:]

modes = {'--sum': sum,
         '--product': prod,
         '--mean': mean}
output_file = stdout

for option in argv[1:-3]:
    if option in modes:
        output_function=modes[option]
    elif option.startswith('--output='):
        output_file = option.split('=')[1]

Changing the code to take an arbirary number of input files is possible, but you will have to assume that your user(s) will remember the required syntax for running your program:

from sys import argv, stdout, exit
from numpy import prod # use math.prod here if you're running Python 3.8
from statistics import mean

input_files = []

modes = {'--sum': sum,
         '--product': prod,
         '--mean': mean}
output_file = stdout

for argument in argv[1:]:
    if argument in modes:
        output_function=modes[argument]
    elif argument.startswith('--output='):
        output_file = argument.split('=')[1]
    elif not argument.startswith('--'):
        input_files.append(argument)
    else:
        print('unexpected option,', argument, 'given! exiting.')
        exit(1)

The example solution above makes the assumption that anything passed on the command line that doesn’t begin with -- must be the name of an input file. This is certainly not the most robust interface ever designed!

Note also that, to encourage good practices, we use the sys.exit function, which you may not have been introduced to before. This function call will cause the script to quit with error code 1 (after printing a semi-helpful error message) when an invalid option is provided.

sys.argv is a great choice when the interface of our program is simple, e.g. when there will be only one or two arguments or when all arguments are the same (e.g. an arbitrary number of files with a consistent format). As the exercise above shows, we would like something a little more advanced once the behaviour of our programs becomes more complex (e.g. we introduce options, or want to define arguments with a limited number of acceptable values, etc).

Handling Options and Arguments with argparse

Another module in the standard library, argparse provides a relatively easy and highly-configurable way to parse command line options and arguments. The minimum we need to do in a script to use an ArgumentParser is:

  1. import the module
  2. create a new ArgumentParser object
  3. call that object’s parse_args method

If we write an example program that contains only these three steps, and run it with the -h flag, we can already see one big advantage of using argparse:

$ cat argparse_example1.py
import argparse

parser=argparse.ArgumentParser()
parser.parse_args()
$ python argparse_example1.py -h
usage: argparse_example1.py [-h]

optional arguments:
  -h, --help  show this help message and exit

That’s right: argparse automatically generates a usage/help message to be displayed for the program, and sets it up to be printed when the user adds the -h flag! Writing good quality and well-formatted documentation such as this can be tedious and time-consuming. argparse saves us that effort, and ensures that this help information is always up-to-date with all the options our program is configured to expect.

Positional arguments

To make our parser useful, let’s configure it to expect a positional argument (an argument whose purpose is implied by its position in the command line), the path to an input file. We tell the ArgumentParser object about the arguments it should expect with the aptly-named add_argument method.

$ cat argparse_example2.py
import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.parse_args()
$ python argparse_example2.py -h
usage: argparse_example2.py [-h] input_file

positional arguments:
  input_file  path to an input file for processing

optional arguments:
  -h, --help  show this help message and exit

The example above shows how the program’s help message has been updated to list this positional argument, along with the description we provided about it with the help parameter. What happens if we now try to run the program without providing that input file path?

$ python argparse_example2.py
usage: argparse_example2.py [-h] input_file
argparse_example2.py: error: the following arguments are required: input_file

The program raises an error (code 2) prints a short description of the intended usage of the script, and a reasonably helpful error message to tell us that we’ve failed to provide an argument the program requires.

To use the values provided as arguments to the program, we need to capture the output of parse_args. Doing so provides us with a object carrying the processed argument values within attributes. This is best understood with another example:

$ cat argparse_example3.py
import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
args = parser.parse_args()

print(f"input_file provided was {args.input_file}")
$ python argparse_example3.py path/to/input.file
input_file provided was path/to/input.file

4.3. Adding More Arguments

Duplicate argparse_example3.py and add two more arguments to the parser, saving the new version as argparse_example4.py. Name the new arguments number1 and number2 and add help messages to tell the user that these are the first and second number they should provide. Finally, adjust the program so it prints these two numbers after the message about the input filepath.

Solution

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("number1", help="the first number")
parser.add_argument("number2", help="the second number")

args = parser.parse_args()

print(f"input_file provided was {args.input_file}")
print(args.number1)
print(args.number2)

4.4. Four’s a Crowd

What happens when you run argparse_example4.py with four arguments, e.g. python argparse_example4.py three 2 1 explosions?

Solution

The parser notices that unexpected information has been provided and raises an error.

usage: argparse_example4.py [-h] input_file number1 number2
argparse_example4.py: error: unrecognized arguments: explosions

By default, the values parsed by ArgumentParser.parse_args are strings (as with sys.argv). To specify that we’d like the two number arguments, number1 and number2, to be parsed as integers, we can use the type parameter of add_argument:

$ cat argparse_example5.py
import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("number1", type=int, help="the first number")
parser.add_argument("number2", type=int, help="the second number")
args = parser.parse_args()

print(f"input_file provided was {args.input_file}")
print(args.number1 + args.number2)
$ python argparse_example5.py path/to/input.file 5 70
input_file provided was path/to/input.file
75

The value provided to this type parameter must be a function that converts a string value to some other data type, e.g. int or float.

Options

The previous examples have demonstrated that, if we define a positional argument, it must be included in the command for the program to be executed without error. Often, we would like to add options - additional settings that can be provided to the program when the circumstances require it (e.g. when working with compressed input, or when we would like to specify a destination file for the program’s output) but may also be left out.

argparse distinguishes between an option and an argument based on the name we give when we call add_argument: names beginning with -- or - are processed as options. For example, to add an option to provide the path to an output file, we might choose the name --output, or -o for short:

import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("number1", type=int, help="the first number")
parser.add_argument("number2", type=int, help="the second number")
parser.add_argument("--output", "-o",
                    help="path to an output file (default: print to STDOUT)")
args = parser.parse_args()

print(f"input_file provided was {args.input_file}")

result = args.number1 + args.number2
if args.output:
    with open(args.output, "w") as outfh:
        outfh.write(f"{result}\n")
else:
    print(result)

If we save this script as argparse_example6.py and run it, with and without providing an output filename with --output=<filename>, we can see how this optional argument is treated differently than the three positional arguments:

$ python argparse_example6.py input.txt 2 3
input_file provided was input.txt
5
$ python argparse_example6.py input.txt 2 3 --output=output.txt
input_file provided was input.txt
$ cat output.txt
5

Configured this way, the optional field still expects a value to be provided i.e. output is an optional argument. However, with a bit of extra work we can also create options that affect the behaviour of a program without the need for the user to specify an associated value. To demonstrate this, we’ll add another option, loud to the example script, which causes the message about the input filename to be shouted back at the user.

import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("number1", type=int, help="the first number")
parser.add_argument("number2", type=int, help="the second number")
parser.add_argument("--output", "-o",
                    help="path to an output file (default: print to STDOUT)")
parser.add_argument("--loud", "-l", action="store_true",
                    help="print info about the input filepath in ALL CAPS")
args = parser.parse_args()

message = f"input_file provided was {args.input_file}"
if args.loud:
    message=message.upper()
print(message)

result = args.number1 + args.number2
if args.output:
    with open(args.output, "w") as outfh:
        outfh.write(f"{result}\n")
else:
    print(result)
$ python argparse_example7.py input.txt 2 3 --loud
INPUT_FILE PROVIDED WAS INPUT.TXT
5

Restricting Input Values

We’ve already seen how to specify the type of value we expect from an argument. Taking this approach saves us from having to remember to convert the value when we want to use it later on, and also has the advantage that input is validated and incompatible values noticed as soon as possible and an error raised before execution reaches the guts of the program. The benefit of this will be painfully apparent to anyone who ever waited hours for their program to run, only for a typo or missing argument in the command line to then cause it to fail.

But what about situations where the type of value isn’t enough? What if only a handful of values are valid for an argument or option? In these cases, we can provide the valid choices as a list to the choices parameter in add_argument:

import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("number1", type=int, help="the first number")
parser.add_argument("number2", type=int, help="the second number")
parser.add_argument("language", choices=["en", "de", "es", "pt"],
                    help="language of logging messages")
parser.add_argument("--output", "-o",
                    help="path to an output file (default: print to STDOUT)")

args = parser.parse_args()

logging_messages = {
    "en": "input file:\t{}",
    "de": "Eingabedatei:\t{}",
    "es": "nombre de archivo de entrada:\t{}",
    "pt": "nome do arquivo de entrada:\t{}",
}

message = logging_messages[args.language].format(args.input_file)
print(message)

result = args.number1 + args.number2
if args.output:
    with open(args.output, "w") as outfh:
        outfh.write(f"{result}\n")
else:
    print(result)
$ python argparse_example8.py -h
usage: argparse_example8.py [-h] [--output OUTPUT]
                            input_file number1 number2 {en,de,es,pt}

positional arguments:
  input_file            path to an input file for processing
  number1               the first number
  number2               the second number
  {en,de,es,pt}         language of logging messages

optional arguments:
  -h, --help            show this help message and exit
  --output OUTPUT, -o OUTPUT
                        path to an output file (default: print to STDOUT)
$ python argparse_example8.py input.txt 2 3 pt
nome do arquivo de entrada:	input.txt
5
$ python argparse_example8.py input.txt 2 3 fr
usage: argparse_example8.py [-h] [--output OUTPUT]
                            input_file number1 number2 {en,de,es,pt}
argparse_example8.py: error: argument language: invalid choice: 'fr' (choose from 'en', 'de', 'es', 'pt')

Default Values

The example served its purpose: it demonstrated how the choices parameter can be used to ensure the user doesn’t pass unexpected values to our program, asking it to speak a language it hasn’t been “taught.” But an argument like this should probably be optional: it might be helpful for another user to be able to adjust the language used in the logging messages, but we’re unlikely to need to change that language from one run to the next on our own system.

This is where it becomes helpful to specify a default value - a value the program will use unless it’s explicitly told by the user to use a different one. As you might have guessed by now, we can specify default values for arguments/options with another parameter to add_argument, default. When we demonstrate its usage below, we’ll also convert the language positional argument to an option, which is more appropriate for input like this.

import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("number1", type=int, help="the first number")
parser.add_argument("number2", type=int, help="the second number")
parser.add_argument("--language", "-l",
                    choices=["en", "de", "es", "pt"], default="en",
                    help="language of logging messages")
parser.add_argument("--output", "-o",
                    help="path to an output file (default: print to STDOUT)")

args = parser.parse_args()

# [... as before ...]
$ python argparse_example9.py -l pt input.txt 2 3
nome do arquivo de entrada:	input.txt
5
$  python argparse_example9.py input.txt 2 3
input file:	input.txt
5

Capturing Multiple Values

Sometimes we want our programs to accept multiple values for the same argument. We may want our script to accept an arbitrary number of input files to be processed in a batch, or we may want to make sure the user provides two (and only two) input files (e.g. forward and reverse FASTQs from paired-end sequencing).

The nargs parameter of add-argument can be used to indicate the number of values expected for the given argument/option. As well as an integer, you can provide the following special character values to nargs:

character behaviour
* Accept any number of values, including zero (values are returned as a list)
+ Accept at least one value (values are returned as a list)
? Accept one or zero values (default must also be set if nargs="?")

4.5. Handling Multiple Values

Make a copy of argparse_example9.py, name it argparse_example10.py, and replace number1 and number2 with a single argument so that the script takes at least one integer value, sums these values, and writes out the result.

Solution

Lines changed are highlighted with # <---.

import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("numbers", type=int, nargs="+",  # <---
                    help="integers to be summed")
parser.add_argument("--language", "-l",
                    choices=["en", "de", "es", "pt"], default="en",
                    help="language of logging messages")
parser.add_argument("--output", "-o",
                    help="path to an output file (default: print to STDOUT)")

args = parser.parse_args()

logging_messages = {
    "en": "input file:\t{}",
    "de": "Eingabedatei:\t{}",
    "es": "nombre de archivo de entrada:\t{}",
    "pt": "nome do arquivo de entrada:\t{}",
}

message = logging_messages[args.language].format(args.input_file)
print(message)

result = sum(args.numbers)  # <---
if args.output:
    with open(args.output, "w") as outfh:
        outfh.write(f"{result}\n")
else:
    print(result)

Mutually Exclusive Arguments

Although argparse.ArgumentParser has many more options, we’re only going to talk about two more here. The first is the add_mutually_exclusive_group method of the ArgumentParser object, which (as you might guess from the name) we can use to define options that cannot be used together in a command. Let’s use this method to add two options, --silent and --verbose, that control how much logging output we get from argparse_example11.py.

import argparse

parser=argparse.ArgumentParser()
parser.add_argument("input_file",
                    help="path to an input file for processing")
parser.add_argument("numbers", type=int, nargs="+",
                    help="integers to be summed")
parser.add_argument("--language", "-l",
                    choices=["en", "de", "es", "pt"], default="en",
                    help="language of logging messages")
parser.add_argument("--output", "-o",
                    help="path to an output file (default: print to STDOUT)")
group = parser.add_mutually_exclusive_group()
group.add_argument("--verbose", "-v", action="store_true")
group.add_argument("--silent", "-q", action="store_true")

args = parser.parse_args()

if args.verbose:
    print("Starting...")

if not args.silent:
    logging_messages = {
        "en": "input file:\t{}",
        "de": "Eingabedatei:\t{}",
        "es": "nombre de archivo de entrada:\t{}",
        "pt": "nome do arquivo de entrada:\t{}",
    }

    message = logging_messages[args.language].format(args.input_file)
    print(message)

if args.verbose:
    print("Calculating result...")
result = sum(args.numbers)
if args.output:
    if args.verbose:
        print("Writing result to file...")
    with open(args.output, "w") as outfh:
        outfh.write(f"{result}\n")
else:
    print(result)

if args.verbose:
    print("Finishing...")

As we’ve come to expect from argparse, the relevant help and error output are generated for us, with the mutually exclusive options separated by a | pipe.

$ python argparse_example11.py -h
usage: argparse_example11.py [-h] [--language {en,de,es,pt}] [--output OUTPUT]
                             [--verbose | --silent]
                             input_file numbers [numbers ...]

positional arguments:
  input_file            path to an input file for processing
  numbers               integers to be summed

optional arguments:
  -h, --help            show this help message and exit
  --language {en,de,es,pt}, -l {en,de,es,pt}
                        language of logging messages
  --output OUTPUT, -o OUTPUT
                        path to an output file (default: print to STDOUT)
  --verbose, -v
  --silent, -q

Let’s check that these flags work as intended:

$ python argparse_example11.py --silent input.txt 2 3 4
9
$ python argparse_example11.py -v -o output.txt input.txt 2 3 4
Starting...
input file:	input.txt
Calculating result...
Writing result to file...
Finishing...

This is a useful example but if you really want to make the verbosity of your programs configurable like this, we recommend you explore another module in the standard library: logging.

While you’re here, if you want fine-grained control on the configuration of your programs and/or you want to make your analyses more reproducible, we recommend you read this book chapter.

Finally, we recommend that you also include some information about the program with the optional description parameter when you initialise your ArgumentParser object:

import argparse

parser=argparse.ArgumentParser(
    description="A multilingual program to calculate the sum of "
                "an arbitrary number of integers "
                "and do something with an input file..."
)

# [...] everything else the same [...]

Note that the strings on individual lines will be interpreted together as a single long string. (This is not special behaviour of ArgumentParser; you can use this approach anywhere, as long as the strings occur inside a set of (), [], or {} - see the Code Style section to learn more about this implied line continuation.)

Now that this description has been added, we are provided with this extra information about the program when we ask for the help message with -h.

$ python argparse_example12.py -h
usage: argparse_example12.py [-h] [--language {en,de,es,pt}] [--output OUTPUT]
                             [--verbose | --silent]
                             input_file numbers [numbers ...]

A multilingual program to calculate the sum of an arbitrary number of integers
and do something with an input file...

positional arguments:
  input_file            path to an input file for processing
  numbers               integers to be summed

optional arguments:
  -h, --help            show this help message and exit
  --language {en,de,es,pt}, -l {en,de,es,pt}
                        language of logging messages
  --output OUTPUT, -o OUTPUT
                        path to an output file (default: print to STDOUT)
  --verbose, -v
  --silent, -q

4.6. Parse Master

Using argparse, write a script process_files.py, with an ArgumentParser configured such that the usage statement below is produced when the script is run with the -h flag.

usage: process_files.py [-h] [--compression {gzip,bzip2}] [--sample SAMPLE]
                        [--qthreshold SCORE]
                        FILE [FILE ...]

Do something to data in (possible compressed) files, involving quality scores
and sample names.

positional arguments:
  FILE                  input files for processing.

optional arguments:
  -h, --help            show this help message and exit
  --compression {gzip,bzip2}, -c {gzip,bzip2}
                        type of compression for input files. leave blank for
                        uncompressed input.
  --sample SAMPLE, -s SAMPLE
                        sample name.
  --qthreshold SCORE, -q SCORE
                        quality score threshold for processing. (default: 30)

Solution

import argparse

parser = argparse.ArgumentParser(
        description="Do something to data in (possibly compressed) files, involving quality scores and sample names."
    )
parser.add_argument("files", metavar="FILE", nargs="+",
                    help="input files for processing.")
parser.add_argument("--compression", "-c",
                    choices=["gzip", "bzip2"],
                    help="type of compression for input files. "
                        "leave blank for uncompressed input.")
parser.add_argument("--sample", "-s", metavar="SAMPLE",
                    help="sample name.")
parser.add_argument("--qthreshold", "-q", metavar="SCORE", type=int,
                    default=30, help="quality score threshold for "
                        "processing. (default: %(default)s)")

parser.parse_args()

Other UI Choices

The exercise above, in which you reverse-engineered an ArgumentParser based on the help message it produced, is reminiscent of the way that docopt, another module for creating command line interfaces, works. With docopt you write the usage of the program, e.g. process_files.py [--option] <argument>, in the file-level docstring. The option/argument parser is then generated at runtime, when the docstring (accessible as __doc__) is processed by docopt.docopt. A standard library module, doctest, has a similar approach, letting you write tests inside the docstring (but this is a topic for another time).

There are additional tools available for creating user interfaces to your Python programs. Two more examples are click and Gooey.

To find out more, we recommend reading this blogpost providing a more thorough comparison of argparse, docopt and click.

4.7 Options & Arguments Revisited

In an earlier exercise, you filled in the blanks in code designed to parse options and arguments from the command line using sys.argv. Use what you’ve learned about argparse to write a parser to replace that code.

As a reminder, after the changes you made earlier, the program should take one (and now only one) of three modes (--sum, --product, --mean) to determine which function will be used in the body of the script, at least one input file, and, optionally, an output file name. Also include the possibility to provide shorthand, single-letter flags (-s, -p, and -m) for each of the modes.

Once you’ve got this parser up and running, try it out. Start by running the script with only the -h flag, then try providing the expected user input, before finally providing some incorrect/incompatible options and/or arguments and observe the result in each case. Do you think this is better than the approach we used before? If so, do you consider the improvement sufficient to be worth the effort?

Solution

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--output_file', "-o", default='',
                    help="path to output file. (default: write to STDOUT)")
parser.add_argument("input_file", nargs='+',
                    help="path to input file(s)")

modes = parser.add_mutually_exclusive_group()
modes.add_argument("--sum", "-s", action='store_true',
                   help="run in 'sum' mode.")
modes.add_argument("--product", "-p", action='store_true',
                   help="run in 'product' mode.")
modes.add_argument("--mean", "-m", action='store_true',
                   help="run in 'mean' mode.")
args = parser.parse_args()

Note that another approach, which might have advantages when trying to implement the different modes within the body of the program, would be to replace the three options in the modes group with a single, required, mode argument accepting three choices: sum, mean, and product.

Key Points

  • Positional command line arguments can be accessed from inside a script through the sys.argv object.

  • The argparse module allows us to create extensive and powerful command line interfaces for our scripts.

  • argparse also constructs a standardised usage statement according to the parser’s configuration.