|$ curl https://forge-ai.dev/api/markdown?path=docs/python/modules
$cat docs/python-—-modules-&-packages.md
updated Recently·15 min read·published
Python — Modules & Packages
◆Python◆Intermediate
Introduction
Modules and packages are Python's mechanism for organizing code into reusable, namespaced units. Every .py file is a module, and directories with __init__.py become packages.
Import System
imports.py
Python
| 1 | # Various import styles |
| 2 | import math # import whole module |
| 3 | from math import sqrt # import specific name |
| 4 | from math import sqrt as sq # import with alias |
| 5 | from math import * # import everything (avoid!) |
| 6 | import math as m # module alias |
| 7 | |
| 8 | # Using imported items |
| 9 | print(math.pi) # → 3.14159... |
| 10 | print(sqrt(16)) # → 4.0 |
| 11 | print(m.floor(3.7)) # → 3 |
| 12 | |
| 13 | # Import path resolution (in order): |
| 14 | # 1. sys.modules (already imported) |
| 15 | # 2. Built-in modules |
| 16 | # 3. sys.path directories (current dir, PYTHONPATH, site-packages) |
| 17 | |
| 18 | # See the module search path: |
| 19 | import sys |
| 20 | print(sys.path) |
| 21 | |
| 22 | # Module caching — modules are imported only once |
| 23 | # Subsequent imports get the cached module object |
| 24 | |
| 25 | # Reload a module (useful in development) |
| 26 | import importlib |
| 27 | importlib.reload(math) # re-execute the module |
✓
best practice
Prefer from module import specific_name over importing whole modules when you only need a few items. It makes dependencies explicit. Never use from module import * in production code — it pollutes the namespace.
Creating Modules
Any .py file is a module. Its name is the filename without .py.
greetings.py
Python
| 1 | # File: greetings.py |
| 2 | """Greetings module — reusable greeting functions.""" |
| 3 | |
| 4 | def hello(name: str) -> str: |
| 5 | return f"Hello, {name}!" |
| 6 | |
| 7 | def goodbye(name: str) -> str: |
| 8 | return f"Goodbye, {name}!" |
| 9 | |
| 10 | PI = 3.14159 # module-level "constant" |
| 11 | |
| 12 | # Module-level code runs once on first import |
| 13 | print(f"Loaded {__name__}") # → Loaded greetings |
| 14 | |
| 15 | # The if __name__ guard |
| 16 | if __name__ == "__main__": |
| 17 | # This code runs ONLY when executed directly: |
| 18 | # python greetings.py |
| 19 | print(hello("World")) |
| 20 | |
| 21 | # Using it: |
| 22 | # import greetings |
| 23 | # print(greetings.hello("Alice")) # → Hello, Alice! |
| 24 | |
| 25 | # __name__ is the module's name: |
| 26 | # - When imported: "greetings" |
| 27 | # - When run directly: "__main__" |
Packages
Packages are directories containing an __init__.py file (can be empty) and module files. They create hierarchical namespaces.
packages.py
Python
| 1 | # Directory structure: |
| 2 | # mypackage/ |
| 3 | # __init__.py |
| 4 | # module_a.py |
| 5 | # module_b.py |
| 6 | # subpackage/ |
| 7 | # __init__.py |
| 8 | # module_c.py |
| 9 | |
| 10 | # __init__.py controls package initialization and exports |
| 11 | # mypackage/__init__.py: |
| 12 | # from .module_a import useful_function |
| 13 | # __all__ = ["useful_function"] # controls `from pkg import *` |
| 14 | |
| 15 | # Importing from packages: |
| 16 | # from mypackage import module_a |
| 17 | # from mypackage.module_a import useful_function |
| 18 | # from mypackage.subpackage import module_c |
| 19 | |
| 20 | # Relative imports (inside a package): |
| 21 | # from . import sibling_module # current package |
| 22 | # from .module_a import helper # sibling module |
| 23 | # from .subpackage import module_c # subpackage |
| 24 | # from .. import parent_module # parent package |
| 25 | |
| 26 | # __init__.py can also do: |
| 27 | # - Package-level imports (convenience API) |
| 28 | # - Package metadata |
| 29 | # - Lazy loading |
Standard Library Highlights
Python's standard library is extensive. These are the modules every Python developer should know:
stdlib.py
Python
| 1 | # os — operating system interface |
| 2 | import os |
| 3 | os.getcwd() # current directory |
| 4 | os.listdir(".") # list files |
| 5 | os.environ # environment variables (dict-like) |
| 6 | |
| 7 | # sys — Python interpreter access |
| 8 | import sys |
| 9 | sys.version # Python version string |
| 10 | sys.argv # command line arguments |
| 11 | sys.exit(0) # exit with status code |
| 12 | |
| 13 | # pathlib — modern filesystem paths (prefer over os.path) |
| 14 | from pathlib import Path |
| 15 | p = Path("/tmp/data/file.txt") |
| 16 | p.parent # → /tmp/data |
| 17 | p.name # → file.txt |
| 18 | p.suffix # → .txt |
| 19 | p.exists() # → bool |
| 20 | p.read_text() # read file content |
| 21 | p.write_text("hello") # write file content |
| 22 | |
| 23 | # json — JSON encoding/decoding |
| 24 | import json |
| 25 | data = {"name": "Alice", "scores": [1, 2, 3]} |
| 26 | text = json.dumps(data, indent=2) # serialize |
| 27 | restored = json.loads(text) # deserialize |
| 28 | |
| 29 | # re — regular expressions |
| 30 | import re |
| 31 | pattern = r"\d{3}-\d{4}" # phone pattern |
| 32 | match = re.search(pattern, "Call 555-1234") |
| 33 | if match: |
| 34 | print(match.group()) # → 555-1234 |
| 35 | |
| 36 | # datetime — dates and times |
| 37 | from datetime import datetime, timedelta |
| 38 | now = datetime.now() |
| 39 | future = now + timedelta(days=7) |
| 40 | formatted = now.strftime("%Y-%m-%d %H:%M") |
| 41 | |
| 42 | # collections — specialized data structures |
| 43 | from collections import defaultdict, Counter, deque |
| 44 | |
| 45 | # itertools — iterator tools |
| 46 | from itertools import chain, product, permutations, groupby |
| 47 | |
| 48 | # functools — higher-order functions |
| 49 | from functools import partial, lru_cache, wraps |
| 50 | |
| 51 | # hashlib — cryptographic hashing |
| 52 | import hashlib |
| 53 | hashlib.sha256(b"hello").hexdigest() |
| 54 | |
| 55 | # uuid — universally unique identifiers |
| 56 | import uuid |
| 57 | uuid.uuid4() |
| 58 | |
| 59 | # statistics — statistical functions |
| 60 | from statistics import mean, median, stdev |
| 61 | |
| 62 | # dataclasses — automatic __init__, __repr__, etc. |
| 63 | from dataclasses import dataclass |
| 64 | |
| 65 | # typing — type hints |
| 66 | from typing import Optional, List, Dict, Tuple |
Package Management
package_management.txt
Bash
| 1 | # pip — Python's package installer |
| 2 | pip install requests # install a package |
| 3 | pip install -r requirements.txt # install from file |
| 4 | pip uninstall requests # remove |
| 5 | pip list # list installed |
| 6 | pip freeze > requirements.txt # save current environment |
| 7 | pip show requests # package details |
| 8 | |
| 9 | # requirements.txt format: |
| 10 | # requests==2.31.0 |
| 11 | # numpy>=1.24,<2.0 |
| 12 | # pytest>=7.0 |
| 13 | |
| 14 | # Modern alternatives (faster): |
| 15 | # uv — Rust-based pip replacement |
| 16 | # uv pip install requests |
| 17 | # uv pip compile requirements.in > requirements.txt |
| 18 | |
| 19 | # Virtual environments (isolate dependencies) |
| 20 | python3 -m venv .venv # create |
| 21 | source .venv/bin/activate # activate (Linux/macOS) |
| 22 | .venv\Scripts\activate # activate (Windows) |
| 23 | deactivate # deactivate |
| 24 | |
| 25 | # Or use: |
| 26 | # python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt |
ℹ
info
Always use virtual environments for project isolation. Modern tools like uv and rye are significantly faster than pip and worth switching to for new projects.
$Blueprint — Engineering Documentation·Section ID: PYTHON-MOD·Revision: 1.0