Packages
A package is Python's way of organizing related modules together under a single namespace. While a module is a single .py file, a package is a directory that contains multiple modules (and possibly subpackages), letting you structure larger codebases into logical, importable units.
What Makes a Directory a Package
Traditionally, a directory becomes a package when it contains a special file named __init__.py. This file can be empty, or it can contain initialization code that runs when the package is first imported — for example, setting up package-level variables or re-exporting names from submodules.
myapp/ ├── __init__.py ├── config.py └── helpers.py
Here, myapp is a package because it has an __init__.py file, and config.py / helpers.py are modules inside it. You could import them like this:
import myapp.config
from myapp.helpers import format_date
myapp.config.load()
format_date('2026-07-06')A Larger Package Structure
Real applications usually nest packages inside packages. Here's a more realistic layout for a small app with a data layer and utilities:
myapp/
├── __init__.py
├── utils.py
├── models/
│ ├── __init__.py
│ ├── user.py
│ └── product.py
└── services/
├── __init__.py
└── billing.pymodels and services are subpackages of myapp — each is its own directory with its own __init__.py, nested inside the parent package's directory.
Subpackages and Dotted Imports
To reach a module inside a subpackage, you chain names together with dots, following the directory path exactly:
from myapp.models.user import User from myapp.models import product from myapp.services.billing import charge_card user = User(name='Ada') charge_card(user, amount=1999)
Each level of nesting (myapp → models → user) corresponds to a directory or file on disk, and each directory along the way needs its own __init__.py (unless you're relying on implicit namespace packages).
Absolute Imports Within a Package
Inside myapp/services/billing.py, you generally want to reference other parts of the package using absolute imports — the full dotted path starting from the top-level package name, exactly as an external caller would write it:
# myapp/services/billing.py
from myapp.models.user import User
from myapp.utils import format_currency
def charge_card(user: User, amount: int) -> str:
return f'Charged {user.name}: {format_currency(amount)}'Absolute imports are unambiguous and easy to read no matter where the file lives. Python's import system resolves myapp.models.user the same way whether it's imported from billing.py, from a test file, or from an interactive shell — as long as myapp's parent directory is on sys.path. (Relative imports, using leading dots like from .user import User, are a related tool covered in depth on the import-system page.)
Controlling Wildcard Imports with __all__
When someone writes from myapp import *, Python needs to decide which names get pulled in. By default, it imports every top-level name that doesn't start with an underscore. You can take explicit control of this with the __all__ list in __init__.py:
# myapp/__init__.py from myapp.utils import format_currency, format_date from myapp.models.user import User __all__ = ['format_currency', 'format_date', 'User']
Now from myapp import * will only bring in format_currency, format_date, and User — nothing else, even if other names exist in the module's namespace. This keeps the package's public surface intentional and predictable.
Why Bother with Packages?
Packages let you group related modules under one namespace instead of dumping dozens of flat
.pyfiles in a single directory.Subpackages mirror your application's domains (models, services, utils) so the file layout documents the architecture.
An
__init__.pygives you a stable place to define a package's public API via imports and__all__, independent of how the internals are split across files.Namespace packages (no
__init__.py) are mostly useful for splitting a single logical package across multiple distributions — most everyday projects are better served by explicit packages.