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:
- 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. - Options: These are values that are associated with a flag. For example, the
-o
flag might be used to specify an output file. - 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]
Argument | Description |
---|---|
-h, –help | show this help message and exit |
-o OUTPUT, –output OUTPUT | The name of the output file |
-r ROWS, –rows ROWS | The number of rows to write |
-c COLUMNS, –columns COLUMNS | The number of columns to write |
-s SEPARATOR, –separator SEPARATOR | The 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
- How would you process the command line arguments and assign the values to local variable for later use?
- At present the arguments are optional, how would you make them mandatory?
- 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.