Programming Fundamentals

Modules and Errors

↩ Back
01

Importing

Reference
Loading a Module

Every Python file is a module. When you write import, Python finds that file, runs it once from top to bottom, and stores the names it defined so your file can reach them.

import math print(math.sqrt(81)) # 9.0 print(math.pi) # 3.141592653589793 print(math.floor(3.9)) # 3
What the import line does
FindsPython looks for a file called math in its own library first, then in the folder of your program.
RunsThe module executes once, no matter how many files import it. A second import reuses what is already in memory.
NamesThe module name becomes a variable in your file, and the dot reaches inside it: math.sqrt, math.pi.
module.name means: look inside module, take the name
Reference
Five Forms of Import

All five forms load the same file. They differ in which names appear in your file and in how much you write at every call.

FormWhat lands in your fileHow you call it
import maththe module, under its own namemath.sqrt(81)
import statistics as stthe module, under a shorter namest.mean(data)
from math import sqrtone name, on its ownsqrt(81)
from math import sqrt, piseveral names, on their ownsqrt(pi)
from math import *every public name in the modulefloor(2.7)
Why the star form is discouraged

With from math import * you no longer know where a name came from, and a module name can silently replace one of yours. If math defines pow and your file defines pow too, one of them disappears without any message.

Interactive
Running Both Imports

The two fragments print the same number. Run them and watch which line the value comes from.

Module then dot
Name on its own
import mathr = math.sqrt(81)print(r)
from math import sqrtr = sqrt(81)print(r)
Output
press run to execute
Output
press run to execute
Now the same call with the wrong form
import mathprint(sqrt(81))
Output
press run to execute

The module is loaded, yet the plain name sqrt was never created in your file, so Python reports a NameError.

02

Standard Library and Third Party

Reference
What Arrives With Python

The standard library is the set of modules that comes inside the Python installation. No download, no version to choose, no folder to prepare: import and the code is there.

ModuleWhat it holdsA call you will use
mathsquare roots, rounding, constantsmath.sqrt(81)
randomrandom numbers and random choicesrandom.randint(1, 6)
statisticsmean, median and mode of a liststatistics.mean(scores)
datetimedates, times and differences between themdatetime.date.today()
timepauses and timestampstime.sleep(2)
osfiles, folders and the system around youos.listdir()
jsontext into data, data into textjson.loads(text)
import random import statistics rolls = [random.randint(1, 6) for i in range(5)] print(rolls) # [3, 6, 1, 4, 4] print(statistics.mean(rolls)) # 3.6
around 200 modules ship with Python and cost nothing to use
Comparison
Standard Library or Third Party
Questionstandard librarythird party
Who wrote itThe Python core teamAnyone, from one person to a company
Where it comes fromInside the installationThe PyPI catalogue, fetched with pip
Before importingNothing to dopip install once, per machine
On a new computerPresent alreadyMissing until installed again
VersionTied to your Python versionChosen by you, and updated separately
Examplesmath, random, json, datetimenumpy, pandas, requests, matplotlib

The import line looks identical in both cases. import json and import pandas are written the same way, and the only difference appears on a machine where pandas was never installed.

Detail
Installing With pip

pip is the installer that comes with Python. It runs in the terminal rather than inside your program, and one install serves every file on that machine.

Terminal
$ pip install requests Collecting requests Successfully installed requests-2.31.0 $ pip list requests 2.31.0 numpy 1.26.4 $ pip uninstall requests
Then, and only then, inside your file
import requests # works once pip has installed it import pandas as pd # the short name is a convention
The message you will meet first

Importing a package that was never installed raises ModuleNotFoundError: No module named 'pandas'. The line is correct Python, so the error appears while the program runs and not when you save the file. In Colab many packages are installed already, which is why the same file can work there and fail on your own computer.

03

Errors

Reference
Two Moments Where a Program Breaks

A syntax error is a sentence Python cannot read, so nothing runs. An exception is a sentence Python read and then could not carry out, so the program runs until that line and stops there.

Syntax error
print("hello" # SyntaxError: '(' was never closed
Detected before the first line runs. No output appears, not even the lines above the mistake.
Exception
print("hello") print(10 / 0) # hello, then ZeroDivisionError
The first line prints. The second one raises, and everything after it is abandoned.

Only the second kind can be caught. try guards lines that Python already understands, so a missing bracket stays your problem and no amount of error handling repairs it.

syntax error: nothing runs · exception: it runs until that line
Reference
Common Exceptions

Every exception carries a name, and the name tells you what kind of promise the line broke. These are the ones you will produce in this course.

NameRaised whenExample
ValueErrorright type, impossible valueint("4x")
TypeErroran operation between wrong types"3" + 5
ZeroDivisionErrora division whose divisor is zero10 / 0
IndexErrora position beyond the last one[1, 2][5]
KeyErrora key that the dictionary lacks{"a": 1}["b"]
NameErrora name never assignedprint(total)
ModuleNotFoundErrorimporting a package never installedimport pandas
Detail
Reading a Traceback

When nothing catches an exception, Python prints a traceback and the program ends. Read it from the bottom, where the name and the message are.

shop.py
prices = [2, 5, 9] print("prices ready") total = 0 for p in prices: total = total + p print(prices[5])
Output
prices ready Traceback (most recent call last): File "shop.py", line 9, in <module> print(prices[5]) IndexError: list index out of range
1
The output above the traceback is real. Everything printed before line 7 already reached the screen, so prices ready tells you the program reached at least that far.
2
The File and line point at the exact place. In longer programs several files appear, and the last one is where the break happened.
3
The copied line shows the code itself, so you can see the expression without opening the editor.
4
The last line is the one that matters: a name before the colon and a description after it. Search that name when you need help, never the whole traceback.
read a traceback from the bottom line upwards
04

try and except

Reference
Guarding a Block

try marks lines that might raise. When one of them does, Python abandons the rest of the block and jumps to the except clause whose name matches. The program continues after the whole structure.

try: age = int(input("Your age: ")) print("In ten years you turn", age + 10) except ValueError: print("Digits only, please") print("the program carries on")
The two paths
Nothing raisedBoth lines of the try block run, the except clause is skipped entirely, and the last print appears.
ValueError raisedThe int call fails, the print inside try never runs, the except clause prints its message, and the last print appears all the same.
Without try, one bad input ends the program. With try, one bad input costs one message.
Reference
The Four Clauses

A full structure has four parts. Only try and except are required, and the other two exist to keep the guarded block as short as possible.

ClauseRuns whenRequired
tryalways, firstyes
except Namean exception of that name was raisedat least one
elsethe try block finished with no exceptionno
finallyalways, last, caught or notno
try: n = int(raw) result = 100 / n except ValueError: print("not a number") except ZeroDivisionError: print("division by zero") else: print(result) finally: print("done")

Several except clauses may follow one try, and Python tests them in the order you wrote. The first name that matches wins and the others are ignored, so a single run never enters two of them.

Why else is worth the extra line

Anything you place inside try is guarded, including code that was never in danger. Moving it to else keeps the try block down to the lines that can really fail, and stops the except clause from catching an error you did not mean to hide.

Interactive
Choose the Input

Three values, one program. Pick a value for raw and run it: the highlight follows the lines Python actually executes, and the panel below collects what reaches the screen.

raw = "40"try: n = int(raw) result = 100 / nexcept ValueError: print("not a number")except ZeroDivisionError: print("division by zero")else: print(result)finally: print("done")
the lines nobody visits stay dim
Output
press run to execute
Every run ends with done, because finally is the one clause no path can avoid.
Detail
Naming the Exception You Expect

A bare except catches everything, including the mistakes you wrote by accident. Naming the exception keeps your handler for the situation you planned and lets the rest reach you as a traceback.

Hides your own bugs
try: n = int(raw) print(totl) except: print("bad input")
The typo in totl raises NameError, and the message blames the user for an error that belongs to you.
Catches one thing
try: n = int(raw) except ValueError: print("bad input") print(totl)
The NameError now stops the program and names your typo, which is exactly what you need while writing code.
Two more forms worth knowing
except (ValueError, TypeError): # one clause, two names print("that value cannot be used") except ValueError as err: # keep the object itself print("Python said:", err) # invalid literal for int()

Repeating the try structure inside a while loop is the usual way to ask again until the value is usable, and it is the pattern most of your programs will end up using.

while True: try: age = int(input("Your age: ")) break except ValueError: print("Digits only, please")
Catch what you can answer. An exception you cannot repair is better left visible.
05

Check Yourself

Question
How Many Lines Print?
The code
try: print("start") print(10 / 0) print("middle") except ZeroDivisionError: print("caught") print("after")
Pick one.
Challenge
Predict Four Outputs

Trace each fragment before pressing Check. The answer button is there for when your trace and the verdict disagree.

type the printed values separated by spaces · quotes and brackets are ignored
1Through the dot
import math print(math.floor(3.9))
2A try that never fails
try: print(int("7") + 1) except ValueError: print("bad")
3Two lines reach the screen
try: print(10 / 0) except ZeroDivisionError: print("caught") finally: print("end")
4A key that is not there
data = {"a": 1} try: print(data["b"]) except KeyError: print("missing")
06

Summary

Recap
What You Can Do Now
1
Import a module in any of the five forms, and say which names each form places in your file.
2
Reach a function through the dot or on its own, and recognise the NameError that follows the wrong choice.
3
Separate a standard library module from a third party package, and install the second one with pip before importing it.
4
Tell a syntax error from an exception, and explain why only one of the two can be caught.
5
Read a traceback from its last line, and name the eight exceptions you meet most often.
6
Write try, except, else and finally, name the exception you expect, and repeat the question until the input is usable.