Free Handbook · Runs in your browser

Modules & Packages

Importing and writing modules, how packages and __init__.py fit together, what if __name__ == "__main__" is for, pip and virtual environments the way professionals use them, and a tour of the standard library you should know exists — plus ModuleNotFoundError and the circular import.

0 / 108 lessons🔥 0 day streak
ShareXLinkedIn

Module 05 · what you'll be able to do

  • Import in all its forms and know which one to use
  • Split a program into modules and a package
  • Explain the __main__ guard and why every script has one
  • Create a virtual environment, install packages with pip, and pin them in requirements.txt
  • Reach for the right standard-library module before installing anything
01

Modules and import

A module is a .py file. import math runs math.py once (top to bottom), then gives you a module object whose attributes are everything the file defined. Any file you write is a module too — import helpers looks for helpers.py next to your script, then along sys.path.

pythonEdit it. ⌘/Ctrl + Enter runs.
You should see
1.4142135623730951
3
Thursday
[('i', 4)]
module json
['load', 'loads']
Your turn
Import random and print five random integers between 1 and 6. Then from random import randint and do it again.

Avoid

  • from os.path import * — pulls in unknown names, shadows your own
  • Importing inside a loop
  • Importing a module for one constant you could copy

Prefer

  • import os then os.path.join(...) — the reader sees where it came from
  • All imports at the top: standard library, then third-party, then your own
  • from x import y for a few names you use constantly
Error you will hit

ModuleNotFoundError: No module named 'requests'

python
import requests
print(requests.get("https://example.com").status_code)
Traceback (most recent call last):
  File "your code", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'
Why the interpreter said that

Python searched every directory on sys.path and found no requests. Three causes, in order of likelihood: (1) the package is not installed in this interpreter — you installed it in a different Python or a different virtual environment; (2) a typo in the name; (3) your own module is not on the path. In this browser page, only the standard library and a few bundled packages exist — the same error you would get on a fresh machine.

The fix

Install it into the environment you are running: python3 -m pip install requests. Using python3 -m pip instead of bare pip guarantees the same interpreter.

02

Packages

A package is a directory of modules with an __init__.py file (it can be empty). Dots in an import walk the directories: from shop.payments import charge means shop/payments.py, function charge. Inside a package you can import siblings relatively: from . import models.

texta project layout that scales
shop/
├── __init__.py          # makes "shop" a package; can expose a public API
├── models.py            # Product, Order
├── payments.py          # charge(), refund()
└── db/
    ├── __init__.py
    └── postgres.py
main.py                  # entry point: from shop.payments import charge
tests/
└── test_payments.py
pythonshop/__init__.py
"""The shop package. Import the public API here so callers write
`from shop import charge` instead of reaching into submodules."""
from .payments import charge, refund
from .models import Product, Order

__all__ = ["charge", "refund", "Product", "Order"]

__all__ defines what from shop import * exports and, more usefully, documents the public surface.

Error you will hit

ImportError: cannot import name 'charge' from partially initialized module (circular import)

python
# shop/payments.py
from shop.orders import Order      # payments needs orders...

# shop/orders.py
from shop.payments import charge   # ...and orders needs payments
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from shop.payments import charge
  File "shop/payments.py", line 2, in <module>
    from shop.orders import Order
  File "shop/orders.py", line 2, in <module>
    from shop.payments import charge
ImportError: cannot import name 'charge' from partially initialized module 'shop.payments' (most likely due to a circular import)
Why the interpreter said that

Importing payments starts running it; on line 2 it imports orders, which on ITS line 2 asks for charge from payments — but payments is still on line 2 and has not defined charge yet. Two modules that each need the other at import time cannot both go first.

The fix

Usually a design smell: move the shared thing into a third module both import, or import inside the function that needs it (so it runs at call time, not import time).

python
# shop/orders.py
class Order: ...

def pay(order):
    from shop.payments import charge   # deferred: runs when pay() is called
    return charge(order)
03

if __name__ == "__main__"

Every module has a __name__. When you run a file directly, its __name__ is "__main__"; when another file imports it, __name__ is the module's name. The guard lets one file be both a library (importable, nothing runs) and a script (run it, and the block executes). Without it, importing your module would also run its demo code, tests, or worse.

pythonEdit it. ⌘/Ctrl + Enter runs.
You should see
this module's __name__ is __main__
hello-world-from-python

In this page the code runs as the main program, so the guard is true. Save it as slug.py, then in another file import slug — the print inside the guard will not run.

The shape of every script
Functions at the top, a main() that wires them together, and if __name__ == "__main__": main() at the bottom. Testable, importable, and readable from the bottom up.
04

pip and virtual environments

Third-party packages come from PyPI via pip. Installing them globally is how you end up with project A needing pandas 1.x and project B needing 2.x. A virtual environment is a private copy of Python plus its own packages, one per project. Every professional Python project uses one; every CI system expects one.

shellterminal — the four commands you need
# 1. create it, once, inside the project folder
python3 -m venv .venv

# 2. activate it (each new terminal)
source .venv/bin/activate          # macOS / Linux
.venv\Scripts\activate             # Windows PowerShell

# 3. install what the project needs
python -m pip install requests pandas

# 4. freeze the exact versions so others (and CI) get the same ones
python -m pip freeze > requirements.txt
# …and on another machine:
python -m pip install -r requirements.txt

Add .venv/ to .gitignore. The environment is rebuilt from requirements.txt; it is never committed.

ToolWhat it isWhen you meet it
venv + pipBuilt in. Enough for most projects.Now
requirements.txtA plain list of pinned packagesEvery deploy, every Dockerfile
pyproject.tomlThe modern project file (name, version, dependencies)Publishing a package, or any tool below
uv / poetryFaster, lockfile-based managers on top of the same ideasTeam projects
condaEnvironments that also manage non-Python binariesData science, ML
Quick check

pip install pandas succeeded, but import pandas in your script says ModuleNotFoundError. Most likely cause?

05

Standard library tour

"Batteries included" is Python's slogan for a reason. Before you pip install anything, check whether the standard library already does it. These are the modules working engineers use every week; the ones with their own lessons later are linked.

pythonEdit it. ⌘/Ctrl + Enter runs.
You should see
3 True
.csv
{"ok": true, "n": 3}
['66', '2']
2026-12-25
b
[('A', 'B'), ('A', 'C'), ('B', 'C')]
5 4
a fairly long [...]
24
True
NeedModuleInstead of installing
Files, directories, pathspathlib, os, shutil
CSV, JSON, configcsv, json, tomllib, configparserpandas, for small files
HTTP (simple)urllib.requestrequests — though requests is nicer
Dates, timesdatetime, zoneinfopytz
Command-line argumentsargparseclick, typer
Loggingloggingprint()
Testingunittestpytest — which most teams still install
Concurrencythreading, asyncio, concurrent.futures
Databasessqlite3anything, for a local database
Hashing, secretshashlib, secrets, uuid

Finish the Python handbook, then get hired

Sit the exam for your certificate, run your resume through the ATS checker, and see the jobs that ask for exactly this.

Check my resume
Found this course useful? Share it.
ShareXLinkedIn

Comments

0

Join the conversation. Sign in to leave a comment — we'd love to hear your thoughts.