Python Modules and Packages
- Description:
importforms, modules vs packages,__init__.py, relative imports,sys.path, the__main__idiom, virtual environments, and modern project metadata (pyproject.toml) - My Notion Note ID: K2A-D1-13
- Created: 2023-02-28
- Updated: 2026-05-11
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
- 1. Modules and Imports
- 2. Packages and
__init__.py - 3. Relative Imports
- 4. How
importFinds Things - 5.
if __name__ == "__main__": - 6. Virtual Environments
- 7.
pyproject.tomland Modern Packaging - 8. Standard Library Highlights
1. Modules and Imports
- A module is a
.pyfile - Importing executes it once and caches it in
sys.modules
import math # use as math.sqrt(2)
import numpy as np # alias
from os import path # bind path directly into this namespace
from os.path import join, dirname
from collections import ( # parenthesized for many names
defaultdict,
Counter,
)
from typing import * # discouraged, pollutes namespace
- Re-importing does NOT re-run; use
importlib.reload(module)to force during dev - Reload only refreshes the module's own bindings, references in other modules still point at old objects
2. Packages and __init__.py
- A package is a directory of
.pyfiles containing__init__.py(may be empty)
mypkg/
__init__.py
core.py
util/
__init__.py
text.py
import mypkg.core
from mypkg.util.text import slugify
__init__.pyruns when the package is first imported
Common uses:
-
Re-export the public surface:
from .core import App→ callers canfrom mypkg import App -
Define
__all__to controlfrom mypkg import * -
Set up package-level constants
-
Implicit namespace packages (PEP 420, no
__init__.py), multiple directories can merge into one logical package; useful for plugin systems
3. Relative Imports
# inside mypkg/util/text.py
from . import config # same package (mypkg.util)
from .. import core # parent package (mypkg)
from ..core import App # specific name from parent
- Resolved by the file's package position, not cwd → survive moves
- Can only be used inside a package,
python text.pymakes them fail withImportError
4. How import Finds Things
sys.path search order:
- Directory containing the script (or
""for cwd in REPL) PYTHONPATHenv var directories- Installation default, stdlib +
site-packagesin the active venv
import sys
sys.path # list of search dirs
sys.modules # cache of already-imported modules
- Editing
sys.pathat runtime works but is fragile, preferpip install -e .so your package lives insite-packages
5. if __name__ == "__main__":
__name__ == "__main__"when run directly__name__is the module's dotted name when imported- The guard lets a file be both a library and a script
def main():
args = parse_args()
run(args)
if __name__ == "__main__":
main()
For packages, add __main__.py so python -m mypkg works:
mypkg/
__init__.py
__main__.py # contains `from .cli import main; main()`
cli.py
6. Virtual Environments
python3 -m venv .venv
source .venv/bin/activate # Linux/macOS
.venv\Scripts\activate # Windows
which python # → .venv/bin/python
pip install -r requirements.txt
deactivate
- Isolates each project's dependencies
- Modern alternatives,
poetry,uv,pdm,hatch,pipenv, manage env + lockfile uvis currently the fastestcondais a separate ecosystem for scientific Python with non-Python deps
7. pyproject.toml and Modern Packaging
- PEP 518/621, canonical project metadata file
- Replaces the old
setup.py/setup.cfg
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
"requests>=2.31",
"click>=8.1",
]
[project.optional-dependencies]
dev = ["pytest", "mypy", "ruff"]
[project.scripts]
mytool = "myproject.cli:main" # creates a `mytool` console script
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Install in editable mode:
pip install -e . # imports live from your source tree
pip install -e ".[dev]" # plus the dev extras
- Build a wheel:
python -m buildoruv build - Upload:
twineoruv publish
8. Standard Library Highlights
| Module | What it gives you |
|---|---|
os, os.path, pathlib |
Filesystem (prefer pathlib) |
sys |
Interpreter state, sys.argv |
subprocess |
Run external commands |
json, csv, tomllib (3.11+) |
Common formats |
re |
Regex |
datetime, zoneinfo |
Dates and time zones |
collections, itertools, functools |
Functional & data-structure helpers |
logging |
Structured logging |
argparse |
CLI parsing |
unittest, doctest |
Built-in test runners |
dataclasses |
Lightweight value types |
typing |
Static type tooling |
concurrent.futures, threading, multiprocessing, asyncio |
Concurrency |
urllib, http, socket |
Networking primitives |
pickle, shelve |
Object serialization (unsafe for untrusted input) |