ReviseAlgo Logo

Modules & Packages

Packages

Organizing modules into hierarchical packages with __init__.py

Interview: Project structure — tested in system design and code organization discussions

Last Updated: June 12, 2026 8 min read

A Python package is a directory containing modules and an __init__.py file. Packages provide a hierarchical namespace for organizing related modules. They're the standard way to structure larger Python projects and are fundamental to the Python package ecosystem.

Package Structure

  • Directory with __init__.py: The directory becomes a package; __init__.py runs on package import
  • Namespace packages: Python 3.3+ supports implicit namespace packages without __init__.py
  • Subpackages: Nested directories with their own __init__.py create subpackages
  • Import paths: from mypackage.sub import module

__init__.py Roles

  • Package marker: Tells Python this directory is a package (can be empty)
  • Package initialization: Code in __init__.py runs when the package is imported
  • Convenience imports: Re-export key names — from .module import MyClass lets users do from package import MyClass
  • __all__ list: Controls what from package import * exports

Modern Package Layout

Modern Python projects use the src/ layout: put your package inside src/mypackage/ with a pyproject.toml at the project root. This prevents import conflicts and makes testing cleaner.

Relative vs Absolute Imports

In packages, use relative imports (from . import sibling) for internal references and absolute imports (from mypackage.utils import helper) for cross-package references. PEP 8 recommends absolute imports for clarity.

Use Cases

Structuring large Python projects into logical, hierarchical packages

Creating distributable Python packages with pyproject.toml

Building internal company libraries with clean public APIs

Plugin architectures using namespace packages

Separating concerns: core logic, utilities, models, views

Common Mistakes

Putting too much logic in __init__.py — slows down imports and creates circular dependencies

Mixing relative and absolute imports inconsistently within a package

Forgetting __init__.py in subdirectories — they won't be recognized as packages (pre-3.3)

Not using src/ layout — can cause import conflicts during testing

Circular package imports — restructure or use lazy imports to fix