As your programs grow, two questions come up. How do I reuse code instead of writing everything myself? And what should happen when something goes wrong, such as a missing file or text where a number was expected? Python modules answer the first question and exceptions the second. This final lesson of the track brings together everything from Python Functions and Python File Handling.
Importing Python modules
A module is simply a Python file whose functions and variables you can use in another file. Python ships with a large standard library of modules, ready to import without installing anything. There are three common forms of import:
| Form | How you use it |
|---|---|
import math | Prefix every name: math.sqrt(16) |
from math import sqrt, pi | Use the names directly: sqrt(16) |
import statistics as stats | A shorter alias: stats.mean(data) |
The first form is the clearest, because the reader can see where each name comes from. Avoid from module import *: it pulls in every name and can silently replace your own variables. Put all imports at the top of the file.
import math
import statistics as stats
from datetime import date
print(math.sqrt(144), math.ceil(4.2), math.floor(4.8))
print(f"Area of a 7 m radius garden: {math.pi * 7 ** 2:.1f} sq m")
rainfall_mm = [120, 85, 240, 310, 95]
print("Mean:", stats.mean(rainfall_mm), "Median:", stats.median(rainfall_mm))
republic_day = date(2026, 1, 26)
tamil_new_year = date(2026, 4, 14)
print(republic_day.strftime("%A, %d %B %Y"))
print((tamil_new_year - republic_day).days, "days apart")12.0 5 4 Area of a 7 m radius garden: 153.9 sq m Mean: 170 Median: 120 Monday, 26 January 2026 78 days apart
Other Python modules worth knowing early are random (random numbers and choices), pathlib, csv and json (from the files lesson), collections and os. The library reference lists them all.
import random
random.seed(2026)
prizes = ["Saree", "Smartwatch", "Gift voucher", "Cookbook"]
print(random.choice(prizes))
print(random.randint(1, 100))
random.seed(2026)
print(random.choice(prizes))Saree 41 Saree
Random numbers are usually different on every run. Calling random.seed() with a fixed number makes the sequence repeat, which is useful for testing: after seeding again with 2026, choice() gives the same prize as before. The exact values can differ between Python versions, so do not rely on a seed for results that must stay identical for ever. For passwords or security tokens, use the secrets module instead of random.
Writing your own module
Any .py file is a module. Save the code below as shop_utils.py. In another file in the same folder, such as main.py, you can then write from shop_utils import add_gst and call add_gst(500).
GST_RATE = 18
def add_gst(amount, rate=GST_RATE):
"""Return the amount including GST."""
return round(amount * (1 + rate / 100), 2)
def format_rupees(amount):
return f"₹{amount:,.2f}"
if __name__ == "__main__":
# Runs only when this file is run directly, not when it is imported
print(format_rupees(add_gst(500)))
print(format_rupees(add_gst(12000, rate=5)))₹590.00 ₹12,600.00
The special variable __name__ is "__main__" when you run the file directly, and the module’s name when it is imported. The if __name__ == "__main__": block therefore runs the quick tests above only when you run shop_utils.py itself. When main.py imports the module, the functions are loaded and nothing is printed.
Installing packages with pip
Beyond the standard library, thousands of free packages are published on the Python Package Index (PyPI). For each project, first create a virtual environment, a private folder of packages, with python -m venv .venv (use py -m venv .venv on Windows). Activate it, then install packages with python -m pip install followed by the package name. This keeps every project’s packages separate.
Errors and exceptions
When Python meets a problem while running, it raises an exception and, if nothing handles it, stops and prints a traceback. Read a traceback from the bottom up: the last line names the exception type and message, such as ValueError: invalid literal for int() with base 10: 'abc', and the lines above show the file and line number where it happened.
| Exception | Typical cause |
|---|---|
ValueError | Right type, wrong value: int("abc") |
TypeError | Wrong type: "5" + 5 |
KeyError | Missing dictionary key |
IndexError | List index out of range |
ZeroDivisionError | Dividing by zero |
FileNotFoundError | Opening a file that does not exist |
Handling errors with try and except
Put code that might fail in a try block and the recovery code in an except block for a specific exception type. An optional else block runs only if no exception happened, and finally always runs, which suits clean-up work. You can also raise exceptions yourself with raise when a function receives a value it cannot accept.
def split_bill(total_text, people):
if people < 1:
raise ValueError("people must be at least 1")
total = float(total_text)
return total / people
for total_text, people in [("1800", 4), ("eighteen hundred", 4), ("1800", 0)]:
try:
share = split_bill(total_text, people)
except ValueError as error:
print(f"Could not split {total_text!r} between {people}: {error}")
else:
print(f"Each person pays ₹{share:.2f}")
finally:
print("-- checked --")Each person pays ₹450.00 -- checked -- Could not split 'eighteen hundred' between 4: could not convert string to float: 'eighteen hundred' -- checked -- Could not split '1800' between 0: people must be at least 1 -- checked --
Follow the three test cases. The first works, so else prints the share. In the second, float() raises a ValueError. The third fails on purpose: our own raise stops an impossible split before the program divides by zero. except ValueError as error stores the exception in a variable so you can show its message, and !r in the f-string prints the value with its quotes, which makes empty or odd text easy to spot. finally runs every time.
Watch out: Do not write a bare except: or catch Exception just to make errors disappear. It hides real bugs, including typos in your own code. Catch only the exceptions you expect and know how to handle, and let the rest show their traceback.
Tip: You have finished the Python track. A good next step is a small project that combines the lessons, such as an expense tracker that saves to CSV or JSON. For ideas on what to learn next, compare this track with the JavaScript track.
