Ojasa Mirai

Ojasa Mirai

Python

Loading...

Learning Level

🟢 BeginneršŸ”µ Advanced
Modules Import BasicsCreating ModulesImport StatementsRelative ImportsImport PathsPackages StructureNamespace PackagesPip & DependenciesModule Performance
Python/Modules Packages/Packages Structure

šŸ¢ Advanced Package Design and Architecture

Design enterprise-grade packages with sophisticated organization and clear interfaces.


šŸŽÆ Multi-Tier Package Architecture

Design packages for scalability and maintainability.

enterprise_app/
ā”œā”€ā”€ __init__.py
ā”œā”€ā”€ _version.py              # Version management
ā”œā”€ā”€ _config.py               # Configuration
ā”œā”€ā”€ api/                     # Public API layer
│   ā”œā”€ā”€ __init__.py
│   └── client.py
ā”œā”€ā”€ core/                    # Core functionality (private)
│   ā”œā”€ā”€ __init__.py
│   ā”œā”€ā”€ models/
│   │   ā”œā”€ā”€ __init__.py
│   │   ā”œā”€ā”€ base.py
│   │   ā”œā”€ā”€ user.py
│   │   └── product.py
│   ā”œā”€ā”€ services/
│   │   ā”œā”€ā”€ __init__.py
│   │   ā”œā”€ā”€ authentication.py
│   │   └── database.py
│   └── utils/
│       ā”œā”€ā”€ __init__.py
│       ā”œā”€ā”€ decorators.py
│       └── validators.py
└── exceptions/              # Custom exceptions
    ā”œā”€ā”€ __init__.py
    └── errors.py

enterprise_app/__init__.py:

"""Enterprise application package."""

from ._version import __version__
from .api.client import Client
from .exceptions import AppError

__all__ = ["Client", "AppError", "__version__"]

# Prevent import of internal modules
__private__ = ["core", "_config"]

enterprise_app/api/__init__.py:

"""Public API."""

from .client import Client

__all__ = ["Client"]

enterprise_app/api/client.py:

"""Public client API."""

from ..core.services.authentication import AuthService
from ..core.models.user import User

class Client:
    """Public-facing client."""

    def __init__(self, api_key):
        self.auth = AuthService(api_key)

    def get_user(self, user_id):
        return self.auth.authenticate()
        # Use private core

šŸ’” Plugin Architecture Pattern

app/
ā”œā”€ā”€ __init__.py
ā”œā”€ā”€ core.py
ā”œā”€ā”€ plugins/
│   ā”œā”€ā”€ __init__.py
│   ā”œā”€ā”€ base.py
│   └── registry.py
└── examples/
    ā”œā”€ā”€ plugin_a.py
    └── plugin_b.py

app/plugins/base.py:

"""Base class for all plugins."""

from abc import ABC, abstractmethod
from typing import Any, Dict

class Plugin(ABC):
    """Base plugin interface."""

    name: str = "Plugin"
    version: str = "1.0.0"

    @abstractmethod
    def initialize(self, config: Dict[str, Any]) -> None:
        """Initialize plugin."""
        pass

    @abstractmethod
    def execute(self) -> Any:
        """Execute plugin logic."""
        pass

    def cleanup(self) -> None:
        """Cleanup (optional)."""
        pass

app/plugins/registry.py:

"""Plugin registry and loader."""

import importlib
import sys
from pathlib import Path
from typing import Dict, Type

from .base import Plugin

class PluginRegistry:
    """Manage plugin lifecycle."""

    def __init__(self):
        self._plugins: Dict[str, Plugin] = {}
        self._registry: Dict[str, Type[Plugin]] = {}

    def register(self, name: str, plugin_class: Type[Plugin]) -> None:
        """Register plugin class."""
        self._registry[name] = plugin_class

    def load(self, name: str, config: Dict) -> Plugin:
        """Load and initialize plugin."""
        if name not in self._registry:
            raise ValueError(f"Plugin {name} not registered")

        plugin_class = self._registry[name]
        plugin = plugin_class()
        plugin.initialize(config)

        self._plugins[name] = plugin
        return plugin

    def execute(self, name: str) -> None:
        """Execute loaded plugin."""
        if name not in self._plugins:
            raise ValueError(f"Plugin {name} not loaded")

        self._plugins[name].execute()

    def discover_plugins(self, plugin_dir: str) -> None:
        """Auto-discover plugins."""
        plugin_path = Path(plugin_dir)
        sys.path.insert(0, str(plugin_path.parent))

        for py_file in plugin_path.glob("*.py"):
            if py_file.name.startswith("plugin_"):
                module_name = py_file.stem
                module = importlib.import_module(module_name)

                # Find Plugin subclasses
                for item_name in dir(module):
                    item = getattr(module, item_name)
                    if (isinstance(item, type) and
                        issubclass(item, Plugin) and
                        item is not Plugin):
                        self.register(module_name, item)

šŸ—ļø Namespace Package Configuration

# Company-wide namespace package structure
# /team_a/company/service_a/__init__.py
# /team_b/company/service_b/__init__.py
# /shared/company/core/__init__.py

# All contribute to "company" namespace!

# company/__init__.py is NOT created (namespace package)

# configuration.py - Setup script
import sys
from pathlib import Path

def setup_namespace_paths():
    """Configure namespace packages."""
    paths = [
        Path("/team_a"),
        Path("/team_b"),
        Path("/shared")
    ]

    for path in paths:
        if str(path) not in sys.path:
            sys.path.insert(0, str(path))

# Usage
setup_namespace_paths()

# Now can import from all locations
from company.service_a import ServiceA
from company.service_b import ServiceB
from company.core import CoreUtilities

šŸ“¦ Version Management and Compatibility

# _version.py
__version__ = "2.1.0"
__version_info__ = (2, 1, 0)

VERSION = __version__

# compatibility.py
import sys
from . import _version

def check_python_version():
    """Ensure compatible Python version."""
    if sys.version_info < (3, 8):
        raise RuntimeError(
            f"Package requires Python 3.8+, "
            f"got {sys.version_info.major}.{sys.version_info.minor}"
        )

def check_dependencies():
    """Verify required dependencies."""
    required = {
        "requests": "2.25.0",
        "numpy": "1.20.0"
    }

    import importlib
    missing = []

    for package, min_version in required.items():
        try:
            module = importlib.import_module(package)
            if not hasattr(module, "__version__"):
                continue

            # Simple version check
            installed = module.__version__
            if installed < min_version:
                missing.append(f"{package}>={min_version}")
        except ImportError:
            missing.append(package)

    if missing:
        raise ImportError(
            f"Missing required packages: {', '.join(missing)}"
        )

# Run checks on import
check_python_version()
check_dependencies()

šŸ’» Public API Management

# __init__.py - Carefully curate public API

from . import _version
from ._exceptions import (
    APIError,
    AuthenticationError,
    ValidationError
)
from .api.client import Client
from .api.models import User, Product

# Version info
__version__ = _version.__version__
__version_info__ = _version.__version_info__

# Public API - what users should import
__all__ = [
    "Client",
    "User",
    "Product",
    "APIError",
    "AuthenticationError",
    "ValidationError",
]

# Hide internals
__private__ = ["core", "api", "_version"]

# Optional: freeze module
def __getattr__(name):
    if name in __private__:
        raise AttributeError(
            f"'{name}' is internal, not part of public API"
        )
    raise AttributeError(f"module has no attribute '{name}'")

šŸ”„ Backward Compatibility Patterns

# Deprecation with migration path
import warnings
from functools import wraps

def deprecated(alternative=None, removed_in=None):
    """Deprecation decorator with migration help."""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            msg = f"{func.__name__} is deprecated"
            if alternative:
                msg += f", use {alternative} instead"
            if removed_in:
                msg += f", will be removed in {removed_in}"

            warnings.warn(msg, DeprecationWarning, stacklevel=2)
            return func(*args, **kwargs)

        wrapper.__deprecated__ = True
        wrapper.__alternative__ = alternative
        return wrapper
    return decorator

# Old API (kept for compatibility)
@deprecated(alternative="process_v2()", removed_in="3.0.0")
def process(data):
    """Deprecated: Use process_v2() instead."""
    return process_v2(data)

# New API
def process_v2(data):
    """New processing function."""
    return data

# Aliasing for compatibility
get_user = get_user_v2  # Old name points to new function

šŸŽØ Package Documentation Structure

mypackage/
ā”œā”€ā”€ __init__.py
ā”œā”€ā”€ core.py
ā”œā”€ā”€ README.md            # Overview
ā”œā”€ā”€ docs/
│   ā”œā”€ā”€ index.rst
│   ā”œā”€ā”€ guide/
│   │   ā”œā”€ā”€ installation.rst
│   │   ā”œā”€ā”€ quickstart.rst
│   │   └── advanced.rst
│   └── api/
│       └── reference.rst
└── CHANGELOG.md         # Version history

Include in __init__.py:

"""
MyPackage - Description of package.

Quick Start:
    >>> from mypackage import Client
    >>> client = Client()
    >>> result = client.process(data)

Documentation:
    Full documentation at: https://mypackage.readthedocs.io

Issues:
    Report issues at: https://github.com/user/mypackage/issues
"""

šŸ”‘ Key Takeaways

  • āœ… Use layered architecture: api, core, utils, exceptions
  • āœ… Expose minimal public API in __init__.py
  • āœ… Use __all__ to define public interface
  • āœ… Implement plugin architecture for extensibility
  • āœ… Manage versions and compatibility explicitly
  • āœ… Deprecate old functions with clear migration paths
  • āœ… Document package thoroughly in docstrings

Ready to practice? Challenges | Quiz


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

Ā© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn