06.2 - Creating & Structuring Packages
What is a Package?
A package is a directory containing Python modules, with an __init__.py file.
mypackage/
├── __init__.py # Makes it a package
├── utils.py # Module
├── validators.py # Module
└── subpackage/
├── __init__.py
└── helpers.py
__init__.py
__init__.py runs when the package is imported. It can:
- Be empty (minimal package)
- Import from submodules to create a clean public API
- Set
__all__for the package
# mypackage/__init__.py
from .utils import format_date, format_currency
from .validators import validate_email
__version__ = "1.0.0"
__all__ = ["format_date", "format_currency", "validate_email"]
Now users can do:
from mypackage import format_date # clean import!
Relative vs Absolute Imports
# Absolute (from project root)
from mypackage.utils import format_date
from mypackage.subpackage.helpers import helper_func
# Relative (within the package)
from .utils import format_date # same package
from ..validators import validate_email # parent package
Rule: Use relative imports within a package, absolute imports from outside.
Modern Project Structure
my_project/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
├── pyproject.toml # build config
├── README.md
└── requirements.txt
pyproject.toml
Modern Python projects use pyproject.toml instead of setup.py:
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.backends.legacy:build"
[project]
name = "mypackage"
version = "1.0.0"
description = "A sample Python package"
requires-python = ">=3.10"
dependencies = [
"requests>=2.31",
"pydantic>=2.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"black>=23.0",
"ruff>=0.1",
]
[tool.black]
line-length = 88
[tool.ruff]
select = ["E", "W", "F"]
Key Vocabulary
| Term | Definition |
|---|---|
| Package | Directory with __init__.py containing modules |
__init__.py | Makes a directory a Python package |
| Relative import | from .module import x — relative to current package |
| Absolute import | from package.module import x — from project root |
pyproject.toml | Modern project configuration file |
src layout | Keeps package under src/ to avoid import confusion |
Summary
- A package is a directory with
__init__.pyand module files __init__.pydefines the package's public API using relative imports- Use relative imports (
from .x import y) within a package - Modern projects use
pyproject.tomlfor configuration - Organize large projects with
src/layout
📄️ 06.1 - Modules & Imports
Organize code with Python modules, understand import mechanics, absolute vs relative imports, and the __all__ convention
📄️ 06.2 - Creating Packages
Build a Python package with __init__.py, submodules, and a proper directory structure
📄️ 06.3 - Virtual Environments & pip
Isolate project dependencies with venv, manage packages with pip, and use requirements.txt and pyproject.toml
📄️ Lab - Module 06
Create a properly structured Python package with modules, __init__.py, and a virtual environment
📄️ Quiz - Module 06
30 questions on modules, packages, imports, virtual environments, and pip