Command Line Arguments

Overview

In this session we will look at how to pass arguments to a Python program from the command line. We will cover the following topics:

  • sys.argv
  • argparse
  • click

What are command line arguments?

Command line arguments are values that are passed to a program when it is run from the command line. These values can be used to control the behavior of the program, for example by specifying input files, output files, or other options.

Typically arguments take three forms:

  1. Flags: These are single characters or words that are used to specify options or settings. For example, the -h flag is often used to display help information about a program.
  2. Options: These are values that are associated with a flag. For example, the -o flag might be used to specify an output file.
  3. Long version : These are similar to flags or options, but are usually longer and more descriptive. For example, the --output flag might be used to specify an output file, –all to represent all files.

When a program is run from the command line, the arguments are passed to the program as a list of strings. In Python, this list is stored in the sys.argv variable, which is part of the sys module.

Using sys.argv

The simplest way to access command line arguments in Python is to use the sys.argv variable. This variable is a list of strings that contains the command line arguments passed to the program. The first element of the list is the name of the program itself, and the remaining elements are the arguments.

Here is an example of a simple Python program that prints out the command line arguments:

#!/usr/bin/env python

import sys

for arg in sys.argv:
    print(arg)

We will start by using this approach to access the command line arguments.

Program design

We are going to design a program over the next two sessions to write out csv (comma separated values) files. It will have a number of command line arguments to control the behavior of the program.

usage: csv_writer.py [-h] [-o OUTPUT] [-r ROWS] [-c COLUMNS] [-s SEPARATOR]
ArgumentDescription
-h, –helpshow this help message and exit
-o OUTPUT, –output OUTPUTThe name of the output file
-r ROWS, –rows ROWSThe number of rows to write
-c COLUMNS, –columns COLUMNSThe number of columns to write
-s SEPARATOR, –separator SEPARATORThe separator to use between values

To start with we will use the sys.argv and only search for the presence of the flags. This will make it evident that we need to parse the arguments to get the values associated with the flags and what complexity this can introduce.

After this we will look at the argparse module which is part of the standard library and provides a more powerful and flexible way to parse command line arguments.

Program structure

As the arguments passed in sys.argv are a list of strings we can see if individual arguments are present by checking if they are in the list. We can then use this information to control the behavior of the program.

We can use the if and in construct to test. For example to test if the -h flag is present we can use the following code:

if "-h" in sys.argv or "--help" in sys.argv:
    print("Help requested")

Have a think about how you would test for the presence of the other flags, hint you can use a loop to iterate over the list of arguments.

Click here to see a possible solution
#!/usr/bin/env python
import sys


def main():
    for arg in sys.argv[1:]:  # sys.argv[0] is the name of the script
        print(f"arg: {arg}")
        if "-h" in arg or "--help" in arg:
            print("found helps")
        elif "-o" in arg or "--output" in arg:
            print("found output")
        elif "-r" in arg or "--rows" in arg:
            print("found rows")
        elif "-c" in arg or "--columns" in arg:
            print("found columns")
        elif "-s" in arg or "--separator" in arg:
            print("found separator")
        else:
            print(f" unknown argument {arg}")


if __name__ == "__main__":
    main()

The example above is not really optimal what are the issues?

Using argparse

The argparse module is part of the Python standard library and provides a more powerful and flexible way to parse command line arguments. It allows you to define the arguments that your program expects, including flags, options, and positional arguments, and automatically generates help messages and error handling.

Here is an example of a simple Python program that uses the argparse module to parse command line arguments:

#!/usr/bin/env python

import argparse

def main():
    parser = argparse.ArgumentParser(description="Generate Random CSV Data")
    parser.add_argument("-o", "--output", help="The name of the output file")
    parser.add_argument("-r", "--rows", type=int, help="The number of rows to write")
    parser.add_argument("-c", "--columns", type=int, help="The number of columns to write")
    parser.add_argument("-s", "--separator", help="The separator to use between values")
    args = parser.parse_args()
    print(args)


if __name__ == "__main__":
    main()

On running this program you will notice that it will automatically generate a help message if you run the program with the -h flag. It will also check the type of the arguments and generate an error if the type is incorrect.

The arguments are added to a parser object using the add_argument method. This method takes a number of arguments to define the behavior of the argument, including the flag, the long version, the type, and a help message. We can access them using the args object for example

print(f"output: {args.output}")

exercise

Using the argparse help here

  1. How would you process the command line arguments and assign the values to local variable for later use?
  2. At present the arguments are optional, how would you make them mandatory?
  3. how would you add a default value for the arguments?
Click here to see a possible solution
#!/usr/bin/env python

import argparse


def main():
    parser = argparse.ArgumentParser(description="Generate Random CSV Data")
    parser.add_argument("-o", "--output", help="The name of the output file", required=True)
    parser.add_argument("-r", "--rows", type=int, help="The number of rows to write", default=10)
    parser.add_argument(
        "-c", "--columns", type=int, help="The number of columns to write", default=10
    )
    parser.add_argument(
        "-s", "--separator", help="The separator to use between values", default=","
    )
    args = parser.parse_args()
    output_file = args.output
    rows = args.rows
    columns = args.columns
    separator = args.separator
    print(f"output: {output_file}")
    print(f"rows: {rows}")
    print(f"columns: {columns}")
    print(f"separator: {separator}")


if __name__ == "__main__":
    main()
    

Using click

Whilst argparse is part of the standard python library click needs to be installed as a separate package. It is a more powerful and flexible way to parse command line arguments. It allows you to define the arguments that your program expects, including flags, options, and positional arguments, and automatically generates help messages and error handling.

pip install click

Here is some starter code for the program using click:

#!/usr/bin/env python

import click


@click.command()
@click.option("-o", "--output", help="The name of the output file", required=True)
def main(output, rows, columns, separator):
    print(f"output: {output}")


if __name__ == "__main__":
    main()

Note that click uses a decorator to define the command and options. The options are defined using the @click.option decorator. The arguments to the decorator define the flag, the long version, the type, and a help message. The arguments are passed to the function as parameters.

We will learn more about decorators in a later session.

exercise

Using the above example replicate the previous argparse demo but using click.

Click here to see a possible solution
#!/usr/bin/env python

import click


@click.command()
@click.option("-o", "--output", help="The name of the output file", required=True)
@click.option("-r", "--rows", type=int, help="The number of rows to write", default=10)
@click.option("-c", "--columns", type=int, help="The number of columns to write", default=10)
@click.option("-s", "--separator", help="The separator to use between values", default=",")
def main(output, rows, columns, separator):
    print(f"output: {output}")
    print(f"rows: {rows}")
    print(f"columns: {columns}")
    print(f"separator: {separator}")


if __name__ == "__main__":
    main()

What next

In the next session we are going to use the previous code as an input to a program to generate our CSV files, we first need to learn about reading and writing files in Python.

Previous
Next