Modules and imports: using code you didn't write
Up to now, every line your programs ran was a line you typed. That stops here — and it is the single biggest jump in your power as a programmer. The reality of real software is that you write a little, and you reuse a lot. Nobody writes their own date math, their own random-number generator, or their own JSON parser from scratch. They import code that experts already wrote, tested, and shared. This lesson is about how to find that code and pull it into your program.
What a module is
A module is just a file of Python code — functions, variables, classes — that someone wrote to be reused. When you bring a module into your program, you get to use everything inside it. You bring it in with the import keyword:
import math # bring in the "math" module
print(math.sqrt(16)) # 4.0 — square root
print(math.pi) # 3.141592653589793
Read math.sqrt(16) as "the sqrt function that lives inside math." That dot is the key idea: after import math, the name math is a container, and you reach the tools inside it with module.thing. The dot means "look inside." This is the same dot you used for string methods (text.upper()) and dict methods (d.items()) — it always means "reach into this thing for a name on it."
:::note Why the math. prefix?
Writing math.sqrt instead of bare sqrt keeps names from colliding. If you had your own variable called pi, an unprefixed import could clash with it. The math. prefix says exactly where sqrt and pi come from — no ambiguity, and a reader instantly knows it's the standard library, not your code.
:::
from … import: grab specific names
If you only need one or two things from a module, you can import them by name with from … import. Then you use them without the prefix:
from math import sqrt, pi # pull just these two names out
print(sqrt(25)) # 5.0 — no math. prefix needed now
print(pi) # 3.141592653589793
Both styles do the same job; pick by readability. import math then math.sqrt(...) is explicit about where things come from (good for clarity). from math import sqrt is shorter when you use a name a lot. You will see both everywhere.
:::warning Avoid from module import *
You may see from math import *, which dumps every name from the module into your program with no prefix. Don't do it: you lose track of where names came from, and two modules can quietly clobber each other's names. Import what you actually use, by name.
:::
You can also rename an import with as — handy when a name is long or when there's a community convention:
import datetime as dt # now refer to it as dt
today = dt.date.today()
print(today) # e.g. 2026-06-23
The standard library: a huge toolbox, already installed
Python ships with the standard library — a large collection of modules that come built in with Python itself. You don't install them; they're already there, ready to import. "Batteries included," people say. A few you'll reach for constantly:
math — square roots, rounding, constants, trig:
import math
print(math.sqrt(81)) # 9.0
print(math.floor(4.8)) # 4 — round DOWN to a whole number
print(math.ceil(4.1)) # 5 — round UP
random — randomness for games, sampling, shuffling:
import random
print(random.randint(1, 6)) # a random whole number 1–6 (like a die)
print(random.choice(["a", "b", "c"])) # one random item from the list
nums = [1, 2, 3, 4]
random.shuffle(nums) # shuffles the list IN PLACE
print(nums) # e.g. [3, 1, 4, 2]
datetime — dates and times, and the math between them:
from datetime import date
d = date(2026, 1, 1)
print(d.year) # 2026
print(date.today()) # today's date
json — turn Python objects into text and back. You'll meet this in depth two lessons from now (it is the format APIs speak), but here's the shape:
import json
data = {"name": "Ada", "age": 30}
text = json.dumps(data) # Python dict -> JSON text (a string)
print(text) # {"name": "Ada", "age": 30}
back = json.loads(text) # JSON text -> Python dict again
print(back["name"]) # Ada
You don't need to memorize what's in the standard library. You need to know it exists and that the first move for any common task ("parse a date," "pick something at random," "read JSON") is "there's probably a module for this" — then a quick search confirms it.
Third-party packages: pip and PyPI
The standard library is huge, but it can't contain everything. The wider world of Python lives in third-party packages — code published by other developers that does not come with Python. To get one, you install it.
Two terms to define:
- PyPI (the Python Package Index, pronounced "pie-pee-eye") is the giant public warehouse where developers upload their packages. Think of it as an app store for Python libraries — hundreds of thousands of them, free.
- pip is the installer — the command-line tool that downloads a package from PyPI and sets it up so you can
importit. (pip ships with Python.)
You run pip in your terminal (the command-line window — you'll set this up properly in the "Run Python locally" lesson), not inside your Python code:
pip install requests
That one command goes to PyPI, downloads the requests package (a wildly popular library for talking to web servers), and installs it. From then on, in your code, it's just another import:
import requests # only works AFTER pip install requests
response = requests.get("https://example.com")
print(response.status_code) # 200 means "OK"
:::note The mental model
The standard library is what comes in the box with Python — already installed, import and go. Third-party packages live on PyPI, and you fetch them with pip install once, after which they import exactly like a built-in module. The only difference is that one install step.
:::
:::tip You'll see pip3 and python -m pip too
On some systems the command is pip3 (to distinguish from old Python 2 tooling), and the most reliable form is python -m pip install requests — that says "use this Python's pip," which avoids confusion when several Pythons are installed. They all do the same thing. The next lessons explain why python -m is the safe habit.
:::
A real warning you'll appreciate later: installing packages straight onto your system gets messy fast, because different projects want different versions of the same package. The fix is a virtual environment — an isolated, per-project bubble for packages. That's a whole lesson coming up ("Run Python on your own machine"); for now, just know the cure exists.
Why it matters
Every guide above this one is, in large part, teaching you which packages to import and how to use them. The Modern Web Dev guide imports a web framework. The Modern AI guide imports an SDK to call a model. The Security guide imports tools to inspect requests. None of that makes sense until import and pip install are second nature. You just learned the move that turns Python from "a language for small scripts" into "a language for building real things on the shoulders of thousands of other developers."
Where this leads: every library and SDK in the next guides arrives through exactly this
import/pip installdoor. See Where this leads next.
Practice
This challenge uses the standard library (which Pyodide has built in), so it runs right here. Use the math module:
Import the math module and write hypotenuse(a, b) that returns the length of the hypotenuse of a right triangle with legs a and b — that is, the square root of (a*a + b*b). Use math.sqrt. For legs 3 and 4 the answer is 5.0.
Checkpoint
Modules and imports
Pass to unlock the Next button belowNext: Files & exceptions →