Modules & Packages

Any .py file is a module that other code can import. A folder of modules is a package. Splitting a program into modules keeps each file focused, and the import system is also how you use the standard library and third-party packages.

Importing

PY imports.py
import math
from random import choice, seed
from datetime import date as Date
import statistics as stats

print(math.sqrt(16), math.pi.__round__(3))
seed(1)
print(choice(["red", "green", "blue"]) in {"red", "green", "blue"})
print(Date(2026, 1, 1).year)
print(stats.mean([2, 4, 9]))
Output
4.0 3.142
True
2026
5
FormUse as
import mathmath.sqrt(16) — clear where every name comes from
from math import sqrt, pisqrt(16) — shorter, for a few frequently used names
import numpy as npAn alias, often a community convention
from math import *Imports everything — avoid; it hides where names come from

Writing your own module

Create a file called geometry.py:

PY geometry.py
"""Simple geometry helpers."""

PI = 3.14159

def circle_area(radius):
    return PI * radius ** 2

def _validate(value):
    if value < 0:
        raise ValueError("must be non-negative")

Then, from another file in the same folder:

PY main.py
import geometry
from geometry import circle_area

print(geometry.PI)
print(circle_area(2))

A leading underscore (_validate) signals that a name is internal to the module — it still can be imported, but it isn't part of the public interface, and from geometry import * skips it.

Modules run once

The first import of a module runs its top-level code and caches the result in sys.modules. Later imports anywhere in the program reuse the same module object. That makes modules a natural place for shared configuration — but also means top-level code should only define things, not do heavy work.

if __name__ == "__main__"

Each module has a __name__. It's "__main__" when the file is run directly, and the module's name when it's imported. This lets a file work both as a script and as an importable module:

PY main_guard.py
def celsius_to_f(c):
    return c * 9 / 5 + 32

def main():
    for c in (0, 37, 100):
        print(f"{c}°C = {celsius_to_f(c)}°F")

if __name__ == "__main__":
    main()
Output
0°C = 32.0°F
37°C = 98.6°F
100°C = 212.0°F

Running python3 temps.py prints the table; import temps from another file just gives access to celsius_to_f without printing anything.

Packages

A package is a folder of modules. A typical project layout:

TXT project layout
shop/
├── pyproject.toml
├── src/
│   └── shop/
│       ├── __init__.py
│       ├── cart.py
│       ├── pricing.py
│       └── payments/
│           ├── __init__.py
│           └── stripe.py
└── tests/
    └── test_cart.py
PY imports_in_package.py
# absolute imports (preferred)
from shop.cart import Cart
from shop.payments.stripe import charge

# inside shop/cart.py, a relative import of a sibling module
from .pricing import apply_discount

__init__.py runs when the package is imported and can re-export the most important names, so users can write from shop import Cart. It can be empty.

Where Python looks for modules

PY search_path.py
import sys
for folder in sys.path:
    print(folder)

Python searches the script's own folder first, then the standard library, then installed third-party packages (site-packages). A common bug: naming your own file random.py or json.py — it shadows the standard-library module of the same name, and imports start behaving strangely.

Exploring a module

PY explore.py
import math

print([name for name in dir(math) if not name.startswith("_")][:8])
print(math.__name__)
print(math.hypot.__doc__.splitlines()[0])
Output
['acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cbrt']
math
Multidimensional Euclidean distance from the origin to a point.

dir(module) lists its names and help(module) shows its documentation — handy in the interactive shell.

The standard library

Python ships with hundreds of modules. Some you'll use often:

ModuleFor
pathlib, shutil, osFiles and folders (lesson 44)
json, csv, tomllib, sqlite3Data formats and a built-in database
datetime, zoneinfo, timeDates and times (lesson 49)
math, random, statistics, decimalNumbers (lesson 48)
reRegular expressions (lesson 50)
collections, itertools, functoolsData structures and functional tools
logging, argparse, subprocessBuilding command-line tools
urllib.request, http.server, asyncioNetworking and concurrency
unittest, doctestTesting (lesson 53)

Try it yourself

Try it yourself
Console output