Modules, Imports & the Standard Library Tour
Every .py file you've written is already a module — and Python ships with hundreds of ready-made ones. Imports are how you use code from other files, and the standard library is the reason Python is called a "batteries-included" language.
Importing: three forms
You've been importing since lesson one — now the full picture. Say you have a file math_tools.py:
# math_tools.py
def add(a, b):
return a + b
PI = 3.14159Form 1: import the module (use everything through the module name):
import math_tools
print(math_tools.add(2, 3)) # 5
print(math_tools.PI) # 3.14159Form 2: import specific names (use them directly):
from math_tools import add, PI
print(add(2, 3)) # 5 — no module prefix neededForm 3: import with a nickname (standard for long names):
import math_tools as mt
print(mt.add(2, 3))You've used all three already: import streamlit as st, from dataclasses import dataclass, import json.
The standard library — batteries included
Every Python installation ships with a massive toolbox. The modules professionals reach for weekly:
| Module | What it does | Example |
|---|---|---|
random | randomness | random.randint(1, 6) |
datetime | dates and times | datetime.now() |
math | advanced math | math.sqrt(16) |
os / pathlib | files and folders | os.listdir(".") |
json | JSON data | json.dumps(data) |
csv | CSV files | csv.reader(f) |
collections | specialized containers | Counter(words) |
itertools | loop superpowers | itertools.combinations(...) |
A taste of three:
import random
print(random.randint(1, 6)) # dice roll
print(random.choice(["a", "b", "c"])) # random pick
print(random.shuffle(my_list)) # shuffle in placefrom datetime import datetime, date
now = datetime.now()
print(now.year, now.month, now.day)
print(now.strftime("%d %B %Y")) # 24 August 2026from collections import Counter
votes = ["a", "b", "a", "a", "c"]
print(Counter(votes)) # Counter({'a': 3, 'b': 1, 'c': 1})
print(Counter(votes).most_common(2)) # [('a', 3), ('b', 1)]That Counter just replaced the manual word-counting pattern from Module 5 — the standard library often has your problem pre-solved.
Your own files as modules
Split a growing script into files, import between them:
# calculations.py
def add(a, b):
return a + b
def area(r):
return 3.14159 * r ** 2# main.py
from calculations import add, area
print(add(2, 3)) # 5
print(area(2)) # 12.56636Both files in the same folder, and main.py can import calculations. This is how apps grow past one file.
The if __name__ == "__main__": mystery, solved
You've seen this line in tutorials. Here's what it means:
# calculations.py
def add(a, b):
return a + b
print("calculations.py is running!") # runs ALWAYS — even on import!Import calculations from main.py and that print fires — surprising! The guard fixes it:
# calculations.py
def add(a, b):
return a + b
if __name__ == "__main__":
print("This only runs when THIS file is run directly")
print(add(2, 3))Python secretly sets __name__ to "__main__" when a file is run directly, and to the module's name when it's imported. The guard says: *"demo code only when run directly; silent library when imported."* Every professional Python file uses it.
Common Errors & Fixes
random.py makes import random import YOUR file. Rename yours.✅ Checkpoint
Counter(["a","a","b"]) give? *(Counter({'a': 2, 'b': 1}))*if __name__ == "__main__": block run? *(Only when the file runs directly — not on import)*json.py dangerous? *(It shadows the stdlib json module)*Next: 🧪 Practice — a full project setup, venv to API call.