Learn Python With Me

An online Python course for beginners in programming

The first session of this course was held during March–June 2020. If you would like to receive an email notification for the next session, please subscribe to my newsletter below.

If you found this course useful and would like to support my work, you can do so by making a donation on Paypal.

Join the community on GetTogether.

Cover image of Python course

Course Outline

[TOC]


LPWM #1

March 25, 2020
Introduction to Python, why use it?, the Mu editor, REPL/Python interpreter. Basic syntax, variables, functions, data types, comments.

Slides

Temperature conversion program: c2f.py

# Convert temperature in celsius to fahrenheit

# temp_c = 8
temp_c = input("What is the temperature today? ")
print("Temperature in celsius is ", temp_c)

# F = 1.8 x C + 32
temp_f = 1.8 * temp_c + 32
print("The temperature in Cork today (F) is ", temp_f)

Notes

Using Python 3’s f-string syntax, the above print statement can be written as:

print(f"The temperature in Cork today (F) is {temp_f}")

LPWM #2

April 1, 2020
Working with strings, reserved keywords, working with lists, accessing list elements, the dir() and len() functions.

Slides
Python 3 documentation


LPWM #3

April 15, 2020
Tuples, Dictionaries, if statement, for loop.

Slides
Zeal offline documentation browser.


LPWM #4

April 22, 2020
More on looping techniques, functions

A while loop executes statements inside the block as long as the condition is true. For example, consider the following code:

number = 0
while number != 10:
    number = int(input("Enter number: "))
print("Done")

When you save and run this code, you will be prompted to enter a number (line 3). If you enter a number other than 10, the condition number != 10 will be true and the while loop will then continue asking for new input.

When you enter the number 10, the while loop completes and the “Done” message will be printed.

A function is a series of statements which returns some value to a caller. It can be passed zero or more arguments which may be used in the execution of the body (source)

Here is a simple function to add two numbers:

def add_numbers(a, b):
    print(a + b)

The def keyword is used to define a new function followed by a name for the function - add_numbers in this case. It takes two numbers (a, b) as arguments and then prints their sum.

To call the function, use:

add_numbers(2, 3)

This will output 5.

An advanced example: currency.py

This script has a function defined called as convert which converts Euro to USD using a set exchange rate. When run, the script will prompt user to enter amount in Euro, do the conversion to USD, add it to a total amount and then print it.

# Convert currency from EUR
def convert(amount, currency="USD"):
    rates = {"USD": 1.08150, "GBP": 0.87865}
    if currency not in rates:
        print(f"{currency} not supported")
        return

    result = amount * rates[currency]
    print(f"Amount in {currency}: {result:.2f}")
    return result


if __name__ == "__main__":

    total = 200
    # Ask user for amount in Euro
    amount = int(input("Enter amount (EUR): "))
    amount_usd = convert(amount=amount, currency="USD")

    total += amount_usd
    print(total)

The return statement in the function is used to return the calculated result.

To convert the Euro amount to GBP, call the convert function like so:

amount_gbp = convert(amount=amount, currency="GBP")

LPWM #5

April 29, 2020
Reading and writing text files

Reading a file involves

  1. Opening file
  2. Reading a line (or lines) from file
  3. Closing file

Sample code demonstrating steps above:

f = open("sample.txt", "r")
line = f.readline()
f.close()

The open() function (line 1) is used for opening a file with the file name as the first argument - sample.txt in this case. The mode in which the file has to be opened is provided as the second argument. Here the file is opened read only (r). The function returns a file object which is stored in variable f.

In the second line, the readline() method of the file object can be used to read a single line from the file. Calling readline() again will read the next line of the file and so on until the end of file is reached.

Finally, the file has to be closed using the close() method to free system resources.

To read all lines from a file, use readlines():

lines = f.readlines()
print(lines)
["This is line 1\n", "This is line 2\n", "This is line 3\n"]

lines will now be a list containing all lines in the file.

The \n at the end of each line is called as a newline character and is used to indicate where a line ends in a file. To remove this character, the str.strip() method can be used:

new_lines = []
for line in lines:
    new_lines.append(line.strip())
print(new_lines)
["This is line 1", "This is line 2", "This is line 3"]

To create (write) a new file

The steps are similiar to reading a file. Use the w mode to the open() function. Please note, the file will be overwritten if it already exists.

data = ["one", "two", "three"]
f = open("sample-write.txt", "w")
for item in data:
    f.write(item + "\n")
f.close()

To append data to an existing file

Use the a mode to the open() function. Data will be added to the end of the file.

data = ["four", "five"]
f = open("sample-write.txt", "a")
for item in data:
    f.write(item + "\n")
f.close()

To read files with large amount of data

Rather than reading all data from a file at once using readlines(), consider using the open() function in combination with a for loop.

large_file = "some_file.txt"
for line in open(large_file):
    # process line
    print(line)

For more information, on reading and writing files, please consult the Input and Output section of the Python tutorial.


LPWM #6

May 13, 2020
The csv module — reading and writing CSV files. Handling errors in programs.

We will use the following data as an example. Save this as expense.csv using a text editor:

Number,Item,Cost
1,Milk,1.49
2,Coffee,1.97
3,Bread,1.49
4,Pizza,2
5,Pet food,4.75

Reading a CSV file

# read_csv.py
import csv

with open("expense.csv", newline="") as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        print(row[0], row[1], row[2])

Process data

# read_csv_total.py
import csv

with open("expense.csv", newline="") as csvfile:
    reader = csv.reader(csvfile)
    next(reader)

    total = 0
    for row in reader:
        print(row[0], row[1], row[2])
        total += float(row[2])
    print("Total cost: ", total)

Using DictReader to handle headers

# read_csv_dict.py
import csv

with open("expense.csv", newline="") as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row["Number"], row["Item"], row["Cost"])

Process data (DictReader version)

# read_csv_dict.py
import csv

with open("expense.csv", newline="") as csvfile:
    reader = csv.DictReader(csvfile)

    total = 0
    for row in reader:
        print(row["Number"], row["Item"], row["Cost"])
        total += float(row["Cost"])
    print("Total cost: ", total)

Handle errors while reading

# read_csv_handle_error.py

import csv

with open("expense_invalid.csv", newline="") as csvfile:
    reader = csv.DictReader(csvfile)

    total = 0
    for row in reader:
        print(row["Number"], row["Item"], row["Cost"])
        try:
            total += float(row["Cost"])
        except ValueError:
            print("ERROR: Invalid entry for cost on Line", row["Number"])
        else:
            print("Total cost: ", total)

LPWM #7

May 28, 2020
In part 1 of this session, I discussed modules from the Python standard library I use frequently — os, sys and time.

time

The time module is useful for getting information related to system time, formating and parsing time from strings among other functions.

time.asctime() prints current time as a string:

import time
print(time.asctime())
Fri May 29 21:07:10 2020

time.localtime() prints current time as a struct_time object:

import time

t = time.localtime()
print(t)
time.struct_time(tm_year=2020, tm_mon=5,
 tm_mday=29, tm_hour=21, tm_min=8, tm_sec=49,
 tm_wday=4, tm_yday=150, tm_isdst=0)

# Now you can access current year
print(t.tm_year)
2020

# or month, or other elements in the
# struct_time object
print(t.tm_mon)
5

time.strftime() can be used to print time in a format you specify:

import time

t = time.localtime()

print(time.strftime("%H:%M", t))
21:24

print(time.strftime("%Y-%m-%d %I:%M %p", t))
2020-05-29 09:24 PM

You can find the complete list of directives for formating in the documentation of strftime.

time.sleep() can be used to pause the program for a specific period of time (seconds):

import time

print("Will now sleep for 3 seconds")
time.sleep(3)
print("Done")

The sys module

The platform property of the sys module contains a string corresponding to the operating system where the script or program is currently running — linux for Linux, win32 for Windows, darwin for macOS etc.,

This can be useful to handle directory/folder paths which will be different between systems:

# The sys module needs to be imported before
# it can be used
import sys

platform = sys.platform

# change directories depending on platform
if platform == "linux":
    os.chdir("/home/vimal/mu_code")
elif platform == "win32":
    os.chdir(r"C:\Users\vimal\mu_code")

The r before the folder path in Windows will treat it as a raw string and ignore characters like \n (newline) or \t (tab).

sys.path is a list containing paths — folders or directories where python will search for modules when you use import module_name. This list can be modified if necessary to include additional paths containing your modules (scripts):

import sys

print(sys.path)
['/usr/bin',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '',
 '/usr/local/lib/python3.8/dist-packages',
 '/usr/lib/python3/dist-packages',
 '/usr/lib/python3/dist-packages/IPython/extensions',
 '/home/vimal/.ipython']

# Add the mu_code directory to path
sys.path.append("/home/vimal/mu_code/")

print(sys.path)
['/usr/bin',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '',
 '/usr/local/lib/python3.8/dist-packages',
 '/usr/lib/python3/dist-packages',
 '/usr/lib/python3/dist-packages/IPython/extensions',
 '/home/vimal/.ipython',
 '/home/vimal/mu_code']

Notice the path /home/vimal/mu_code has been added to the end of the list.

sys.argv can be used for accepting information when the program is run from the command line. Using the currency converter program (LPWM #4) as an example:

python convert.py 10

Here 10 is the amount of euros we would like to convert. To capture this information within the script, use:

import sys

print(sys.argv)
['convert.py', '10']

amount = sys.argv[1]
print(amount)
10

The first item in the sys.argv list will be the name of the program — convert.py. There are some exceptions to this.

The os module

The os module can be used for operating system related functions like creating, removing, changing into directories or getting the current directory among others.

import os

# Print current directory
print(os.getcwd())
/home/vimal/mu_code

# Create a directory (should not exist)
os.mkdir("stdlibs")

# Change into the newly created directory
os.chdir("stdlibs")
print(os.getcwd())
/home/vimal/mu_code/stdlibs

# Change into parent directory (.. stands for parent)
os.chdir("..")

# Remove the stdlibs directory (should be empty)
os.rmdir("stdlibs")

LPWM #8

June 10, 2020
The following modules from the standard library were discussed in this session — os.path, glob, argparse and json

os.path

Path manipulations using os.path:

import os.path

f = '/usr/bin/python3'
print('Original file name: ', f)
print('Basename: ', os.path.basename(f))

# Get the directory the file is in
print('Directory: ', os.path.dirname(f))
print('Split path: ', os.path.split(f))

# splitext is not applicable in this case but useful for
# file names with extensions, for example /usr/lib/python3.8/os.py
print('Split file name and extension: ', os.path.splitext(f))

print('Does file exist? ', os.path.exists(f))
print('Is this a file? ', os.path.isfile(f))
print('Is this a directory? ', os.path.isdir(f))

glob

Get all file names matching a pattern using glob:

import glob
files = glob.glob('/usr/lib/python3.8/*.py')
print(files)

# get all file names starting with c and ending in .py
files = glob.glob('/usr/lib/python3.8/c*.py')
print(files)

pprint

Pretty print output using pprint:

import pprint
pprint.pprint(files)

argparse

Get arguments on the command line using argparse:

import argparse

parser = argparse.ArgumentParser(description='Program to add numbers')
parser.add_argument('number1', type=int, help='First number')
parser.add_argument('number2', type=int, help='Second number')
parser.add_argument('-v', '--verbose', help='Get more information', action='store_true')

args = parser.parse_args()
number1, number2 = args.number1, args.number2

if args.verbose:
    print(f'Adding numbers {number1} and {number2}')
print(number1 + number2)

json

Read and write JSON formatted data using json:

import json

data = {'program': 'Python', 'version': 3.8}
print(json.dumps(data))

# # Store JSON
with open('data.json', 'w') as f:
    json.dump(data, f)

# # Read JSON
with open('data.json') as f:
    data_read = json.load(f)
    print(data_read)

LPWM #9 (Final)

June 24, 2020
Sample programs, Q&A

Useful resources

Python cheat sheet (simple)
Python cheat sheet (detailed)
HumbleBundle
Python Crash Course 2nd edition
Automate the Boring Stuff with Python (also on Udemy)
MIT’s Introduction to Computer Science and Programming Using Python
Python Jumpstart by Building 10 Apps
Official Python documentation

Working with databases — sqlite3 module

import sqlite3

# connect to the database
conn = sqlite3.connect("data.sqlite")

# get a cursor to work with
cursor = conn.cursor()

# create table
sql = "create table repeats(key text, gene text, orientation text, status text)"
cursor.execute(sql)

# insert a row
sql = "insert into repeats values (?, ?, ?, ?)"
data = ("M83", "thrA", "F", "Unfinished")
cursor.execute(sql, data)

# insert multiple rows
data = (("M83", "thrA", "R", "Unfinished"), ("AU123", "adk", "F", "Unfinished"))
cursor.executemany(sql, data)

# update data
sql = "update repeats set status=? where key=? and gene=? and orientation=?"
data = ("Finished", "M83", "thrA", "F")
cursor.execute(sql, data)

# commit changes
conn.commit()

#retrieve all data
sql = "select * from repeats"
cursor.execute(sql)
for row in cursor.fetchall():
    print(row)

#close the connection
conn.close()

Comments