Index Ai Academy
Phase 0 · Tools · Python core

Modules and imports

Use Python's standard library instead of reinventing it.

About 20 minutes · Free lesson

Start this lesson

Why it matters

Nobody writes AI software from scratch. The top of every AI script is a list of imports: json to read API replies, requests to call APIs, numpy for the math, the Anthropic SDK to talk to models. Once you know how imports work, and what Python's standard library already does, you reuse proven code instead of rewriting it. You can also read the first ten lines of any project and know what it depends on.

What you'll be able to do

  • Import a module, or specific names from it, and use what it provides
  • Use the standard library for math, randomness, dates, statistics and counting
  • Explain what a module is and where Python looks for one
  • Avoid the import mistakes that confuse beginners

What it covers

  1. Borrowing code with import
  2. A short tour of the standard library
  3. What a module really is
  4. Common import mistakes
  5. Worked example: a week of orders
  6. When an import goes wrong

Borrowing code with import

Think of a toolbox you borrow from a neighbor. You don't build a drill from scratch; you borrow one that already works. A module is that toolbox: a file of Python code, full of functions and values, that you can load into your program. Python ships with hundreds of them, called the standard library. Here's the math module:

import math

print(math.sqrt(144))
print(math.ceil(4.2))
print(math.floor(4.8))
print(math.pi)
It runs right here in your browser, with nothing to install.

import math loads the module once. It gives you a name, math, to reach inside it with a dot: math.sqrt, math.pi. The dot means "the thing called sqrt that lives in math".

ceil rounds up and floor rounds down. That matters when you're working out how many batches, pages or boxes you need.

Three ways to import

import statistics
from math import floor, ceil
import datetime as dt

print(statistics.mean([12, 18, 21]))
print(floor(7.9), ceil(7.1))
print(dt.date(2026, 11, 27).strftime("%A"))
  • import statistics brings in the whole module. You write statistics.mean every time, which makes it obvious where mean came from.
  • from math import floor, ceil brings in specific names, so you write floor(...) directly.
  • import datetime as dt gives the module a shorter alias. Some aliases are universal conventions you'll see in every data and AI project: import numpy as np, import pandas as pd.

You may also meet from math import *, which dumps every name from the module into your program. Avoid it. Readers can no longer tell where a name came from, and it can silently replace your own variables.

Quick check
After from math import sqrt, which line works?
  1. sqrt(9)
  2. import.sqrt(9)
  3. Math.sqrt(9)
  4. math.sqrt(9)
Show the answer

sqrt(9)

from math import sqrt brings in the name sqrt only. The name math itself was never imported, so math.sqrt is a NameError.

A short tour of the standard library

random picks and shuffles. Setting a seed makes the "random" results repeatable. You'll do this constantly in machine learning, so experiments can be reproduced:

import random

random.seed(7)
subject_lines = ["Last chance", "New arrivals", "Your weekly picks"]
print(random.choice(subject_lines))
print(random.randint(1, 100))

datetime handles dates and the gaps between them. A timedelta is a length of time:

from datetime import date, timedelta

launch = date(2026, 11, 27)
reminder = launch - timedelta(days=7)
print("Launch:", launch)
print("Send reminder on:", reminder)
print("Days between:", (launch - reminder).days)

statistics covers the basics. Notice how the one big day pulls the mean up, while the median (the middle value when sorted) barely moves:

import statistics

daily_signups = [42, 38, 51, 47, 39, 120, 44]
print("mean:", round(statistics.mean(daily_signups), 1))
print("median:", statistics.median(daily_signups))
print("stdev:", round(statistics.stdev(daily_signups), 1))

For marketers: when a report shows an average order value, ask whether a few huge orders are inflating it. The median is often the more honest "typical" number.

collections.Counter counts things:

from collections import Counter

sources = ["google", "newsletter", "google", "instagram", "google", "newsletter", "direct"]
counts = Counter(sources)
print(counts["google"])
print(counts["tiktok"])
print(counts.most_common(2))

most_common(2) returns the top two as pairs in parentheses, like ('google', 3). Those are tuples: fixed-size groups of values, like small lists that can't be changed. Asking a Counter for something it never saw gives 0 rather than an error.

Quick check
What does this print?
import statistics
print(statistics.median([10, 20, 30, 400]))
  1. 20
  2. 115.0
  3. 25.0
  4. 400
Show the answer

25.0

With an even number of values, the median is halfway between the middle two: 20 and 30 give 25.0. The mean would be 115, pulled up by the 400.

What a module really is

There's nothing special about a module: it's a .py file. Suppose a folder holds two files:

# metrics.py
def roas(revenue, spend):
    if spend == 0:
        return 0
    return revenue / spend
# report.py
import metrics

print(metrics.roas(15840, 3120.5))

Running report.py makes Python look for metrics.py, run it once, and give you its contents as metrics. Python searches for a module in this order:

  1. the folder of the script you're running,
  2. the standard library,
  3. third-party packages you've installed (the packages lesson covers installing them).

You'll often see this at the bottom of a script:

if __name__ == "__main__":
    main()

__name__ is "__main__" only when the file is run directly, not when it's imported. So this line means: "run main() when someone runs this file. Don't run it when another file imports this one to borrow its functions."

Try it now

This explains the classic mistake: name your own file random.py and Python finds yours first.

Common import mistakes

The module isn't there. A typo, or a third-party package that isn't installed, gives a ModuleNotFoundError:

import maths

You named your file after a module. Save your own script as random.py or json.py, and import random will find your file first, because it's in the script's folder. The symptom is a baffling AttributeError, such as "module 'random' has no attribute 'choice'". Rename your file.

You forgot the prefix. After import math, plain sqrt(4) is a NameError. Write math.sqrt(4).

Quick check
You save your script as json.py, and import json then json.loads(...) fails with an AttributeError. Why?
  1. The json module was removed from Python
  2. Python imported your own json.py from the script's folder instead of the standard library's
  3. loads only works on files
  4. You need to write from json import *
Show the answer

Python imported your own json.py from the script's folder instead of the standard library's

Python looks in the script's folder first, so your file hides the real module. Rename your file.

Worked example

Worked example: a week of orders

Summarize a week of orders: count, average and median order value, the top traffic source, and how many days the data covers.

import statistics
from collections import Counter
from datetime import date

order_values = [64, 28, 92, 18, 45, 64, 130, 22]
order_sources = ["google", "email", "google", "instagram", "email", "google", "direct", "search"]
first_order = date(2026, 11, 23)
last_order = date(2026, 11, 29)

top_source, top_count = Counter(order_sources).most_common(1)[0]

print("Orders:", len(order_values))
print("Average order value:", round(statistics.mean(order_values), 2))
print("Median order value:", statistics.median(order_values))
print("Top source:", top_source, f"({top_count} orders)")
print("Days covered:", (last_order - first_order).days + 1)
In the lesson you can change this and run it.

It reports 8 orders, an average of 57.88, a median of 54.5, google as the top source with 3 orders, and 7 days. The one big 130 order pulls the average above the median.

Three imports replace dozens of lines of hand-written counting, sorting and date arithmetic. most_common(1) returns a list holding one pair. [0] takes that pair, and top_source, top_count = ... unpacks it into two variables. The days calculation adds 1, because both the first and last day count.

When an import goes wrong

Three import problems account for nearly every confusing error here.

The two ways of importing give you different names. After import math, you write math.sqrt(9). After from math import sqrt, you write sqrt(9), and the name math doesn't exist. Mixing them gives a NameError, so check how the top of your file imported it.

You can hide a module by accident. If you save your own file as random.py or json.py, Python finds yours first, and the real module seems to have lost all its functions. If an import suddenly behaves strangely, look at your own file names.

Not everything needs installing. math, json, random and hundreds more come with Python. That's the standard library. Installing is only for outside packages, which you'll meet shortly. It's also why from module import * is best avoided: it pours in names from everywhere, and nobody reading the code can tell where they came from.

Practice what you just read

  • 11 code examples you can edit and run
  • a practice exercise that checks your code
  • a 5-question quiz
  • 5 review cards for spaced repetition

Start this lesson

Try a quiz question

You save a script as random.py. Inside it, import random then random.choice([1, 2]) fails with an AttributeError. Why?

  1. Python imported your own random.py instead of the standard library module
  2. The random module has to be installed with pip before you can import it
  3. choice was removed from recent versions of Python and now lives in another module
  4. You have to write from random import * instead of a plain import

Answer it at the end of the lesson to see if you're right, and why.

Before this lesson