9.0 -- Scripting basics
Getting started with scripting in Python¶
Learning objectives¶
By the end of this tutorial you should:
- Understand the basic building-blocks of a python script
- Understand how the
__main__
keyword defines the behavior of the script - Be able to use
argparse
to allow scripts to accept arguments of different kinds. - Use
print
statements for simple debugging
What is a script?¶
A script is just a text file that contains computer code. Python scripts should end
with .py
. Python scripts are executable at the command line, and this makes them
very useful for developing bioinformatics tools. Let's see how scripts are developed.
Hello world, the simplest example script¶
Here is the simplest executable python script (which I will call myFirstScript.py
).
#!/usr/bin/env python
if __name__ == "__main__":
print("Hello world")
You can probably guess what this script does, but you can try running it yourself
on the command line: python myFirstScript.py
.
What makes this script executable is the funny looking if __name__ == "__main__"
conditional test. Everything inside this if statement is run when the code
is executed at the command line.
Adding imports and functions¶
Lets add a bit of functionality to generate a random password of a given length.
We'll need the string
and random
from the standard library, so we'll import
those at the top (as usual).
Now we write a new function inside our script called random_password
which
accepts 1 argument, being the length of the password, and we call this
function from inside the __main__
block.
#!/usr/bin/env python
import random
import string
def random_password(length=10):
# Define the set of available characters to sample from
chars = string.ascii_letters + string.digits + string.punctuation
# Generate a sample from this list
password = random.choices(chars, k=length)
# password is a list of characters here so `join` them together into
# a string
return "".join(password)
if __name__ == "__main__":
print(random_password())
Adding flexibility with arguments¶
This is great because the passwords look strong, but what if you want
to generate passwords of different lengths? The argparse
module
gives you a powerful way of adding command line arguments to your python
scripts. Let's import it at the top of the file (Note: imports
are
normally sorted alphabetically, unless you have a good reason not to).
#!/usr/bin/env python
import argparse
import random
import string
def random_password(length=10):
chars = string.ascii_letters + string.digits + string.punctuation
password = random.choices(chars, k=length)
return "".join(password)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-l", help="Password length in characters",
dest='length', type=int, default=10)
args = parser.parse_args()
print(random_password(length=args.length))
There are 3 things happening here, most of the action is in the second part (adding new arguments to the parser):
- You create the
parser
object - You add arguments to the
parser
, which themselves can take many different arguments - You call
parse_args()
to return a dictionary-like object containing data for the arguments specified.
When declaring arguments there can be few or many argument parameters. In the above example these were:
-l
: The command line flag to identify this argumenthelp
: The help message to print for argument usagedest
: The destination variable for the value of this argument (notice that we access the value asargs.length
)type
: Theint
type directs argparse to cast the value to an integerdefault
: Set the default value, in the case no value is passed in for this argument. If no default is set then the command line will complain about missing required values.
Here's another nice thing argparse does for you. It automatically generates a helpful
help message when -h
is passed in at the command line, e.g.:
$ python myFirstScript.py -h
usage: myFirstScript.py [-h] [-l L]
options:
-h, --help show this help message and exit
-l L Password length in characters
Providing helpful information with verbose
¶
It's very common for command line programs to have a flag for increasing the verbosity (printing more progress messages). This can also be very helpful for debugging programs, as it allows you to toggle how much or how little your program is communicating to you (which, if it is working fine you probably want it to communicate very little besides the target output).
#!/usr/bin/env python
import argparse
import random
import string
def random_password(length=10, verbose=False):
if args.verbose:
print(f"Generating password length: {length}")
chars = string.ascii_letters + string.digits + string.punctuation
password = random.choices(chars, k=length)
return "".join(password)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-l", help="Password length in characters",
dest='length', type=int, default=10)
parser.add_argument("-v", "--verbose", help="increase output verbosity",
action="store_true")
args = parser.parse_args()
if args.verbose:
print(args)
print(random_password(length=args.length, verbose=args.verbose))
Above we added one more argument now called verbose
. Here we are doing a couple
things different: We specify that it can be invoked either as -v
or as
--verbose
, and we now tell it to action="store_true"
. The store_true
action sets the value of verbose
to True if it is invoked, and False
otherwise.
The other thing we did is to propagate the verbose
argument into the
random_password
function, so that we can also toggle verbosity
inside this function. This is a very common practice in python scripts.
Check the help message of the new function:
$ python myFirstScript.py -h
usage: myFirstScript.py [-h] [-l LENGTH] [-v]
options:
-h, --help show this help message and exit
-l LENGTH Password length in characters
-v, --verbose increase output verbosity
And check the output with the new arguments:
$ python myFirstScript.py -v -l 30
Namespace(length=30, verbose=True)
Generating password length: 30
;GCM5y20>s+^zOF~QG,M@A+80N[6;#