One File Is a Module
Once your Python code grows past a single script, you'll want to split it into multiple files. Python's module system is simple: any .py file is automatically a module, importable by name.
Say you have a file util.py:
# util.py
def greet(name):
return f"Hello, {name}"
PI = 3.14159
From another file in the same directory — main.py — you can use it:
# main.py
import util
print(util.greet("Ada"))
print(util.PI)
Run python3 main.py and Python finds util.py, runs it once, and exposes everything defined at the top level (functions, variables, classes) as attributes of the util module.
The Three Forms of Import
Import the whole module. Things inside are accessed through the module name:
Import specific names. They become directly available:
Import with an alias. Useful when the module name is long or when two modules share a name:
import numpy as np
import pandas as pd
# Now use np.array(...), pd.DataFrame(...), etc.
There's a fourth form, from math import *, that pulls everything into your namespace. Avoid it outside of REPL experimentation — it makes it impossible to tell where a name came from, and it creates silent name collisions.
When Imports Run
Python executes an imported module's top-level code once, the first time it's imported in a given program. Subsequent imports of the same module return the already-loaded version. So this:
# setup.py
print("setup module loading...")
VALUE = 42
# main.py
import setup
import setup # imported twice — but "loading" only prints once
print(setup.VALUE)
Only prints "setup module loading..." once. This matters: if you put side effects (like opening a file or printing) at module top level, they happen at import time, which is usually not what you want. Put those inside functions.
The Standard Library
Python ships with a large standard library of modules. You've already seen a few. Some you'll reach for constantly:
math— sqrt, sin, log, constants likepiande.random— random numbers, choices, shuffling.datetime— dates and times.json— read/write JSON.os,os.path— file system paths and operations.pathlib— modern path handling, often nicer thanos.path.re— regular expressions.collections— specialised collection types (Counter,defaultdict,deque, etc.).itertools,functools— iterator and function helpers.csv— reading and writing CSV files.
Standard library is already installed — nothing to pip install.
Third-Party Packages and pip
For anything the standard library doesn't cover, the Python Package Index (PyPI) hosts hundreds of thousands of packages. Install them with pip:
pip install requests
pip install pandas
pip install --upgrade requests
pip uninstall requests
Once installed, they import like anything else:
import requests
response = requests.get("https://api.example.com/data")
print(response.status_code)
A few tips on managing this sanely:
Use virtual environments
Installing everything globally leads to pain. Different projects need different versions; some packages depend on specific Python versions; global installs require admin rights on some systems. A virtual environment is an isolated Python install just for one project:
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux
.venv\Scripts\activate # Windows
pip install requests
While the venv is activated, pip installs into the project folder, not your system. Deactivate with deactivate when you're done.
Pin your dependencies
Save the list of installed packages so others (including future you) can recreate the same environment:
pip freeze > requirements.txt
Then later:
pip install -r requirements.txt
Tools like Poetry, pipenv, and uv handle this more ergonomically, but the plain pip + requirements.txt workflow is still fine for learning.
Writing Your Own Modules
Once you have functions you want to reuse across files, put them in their own module. Naming conventions:
- File names should be
lower_snake_case.py. - Module-level functions and variables also
lower_snake_case. - Classes use
PascalCase.
# shopping.py
PRICES = {"apple": 0.50, "bread": 2.00}
def total(items):
return sum(PRICES[item] for item in items)
# main.py
from shopping import total, PRICES
print(total(["apple", "bread"]))
print(PRICES)
If two files in the same folder import each other, you can accidentally create a circular import. The usual fix is to move the shared code to a third file both of them import.
Packages: Folders of Modules
Once you have more than a handful of modules, group them into a package — a folder with an __init__.py file in it:
myproject/
├── main.py
└── utils/
├── __init__.py
├── text.py
└── numbers.py
Then:
from utils.text import slugify
from utils import numbers
print(slugify("Hello, World"))
print(numbers.mean([1, 2, 3]))
The __init__.py can be empty; its presence is what makes utils a package. Modern Python also supports "namespace packages" without __init__.py, but for starting out, the explicit version is clearer.
A Tiny Checklist When Imports Break
- "ModuleNotFoundError: No module named X". Either the package isn't installed, or you're running Python from a different interpreter than the one you ran
pip installagainst. In a venv, make sure the venv is activated. - "ImportError: cannot import name Y from X". The module exists, but the name you asked for isn't there. Check for typos and look at the module's actual contents.
- "Circular import". Two modules import each other. Move the shared code to a third module.
Next: Installing Third-Party Packages
Your own modules get you far, but most real projects also pull in libraries from PyPI — requests, pandas, a test framework. The next page covers pip, how to install packages cleanly, and how to record what your project depends on.
Frequently Asked Questions
What is a module in Python?
A module is any .py file. Python files automatically become modules — you import them by name (without the .py). The standard library is a large collection of built-in modules like math, json, and datetime that come with every Python install.
What's the difference between import X and from X import Y?
import X imports the whole module and you access things inside it with X.something. from X import Y pulls only Y into your namespace so you can use it as Y directly. The first form is safer (no name collisions); the second is more compact.
How do I install a Python package?
Use pip install package_name in your terminal. pip is Python's package manager and comes bundled with modern installs. For project isolation, create a virtual environment first so installed packages don't leak between projects.