Ojasa Mirai

Ojasa Mirai

Python

Loading...

Learning Level

🟢 Beginner🔵 Advanced
Modules Import BasicsCreating ModulesImport StatementsRelative ImportsImport PathsPackages StructureNamespace PackagesPip & DependenciesModule Performance
Python/Modules Packages/Import Statements

🚀 Advanced Import Techniques and Optimization

Learn advanced import patterns for complex projects and performance optimization.


🎯 Circular Import Resolution

Handle circular imports elegantly in complex codebases.

# ❌ Problematic circular imports
# models.py
from . import views

class User:
    def render(self):
        return views.render_user(self)

# views.py
from . import models

def render_user(user):
    return models.User  # Circular!

# ✅ Solution 1: Late imports
# models.py
class User:
    def render(self):
        from . import views  # Import inside method
        return views.render_user(self)

# views.py
from . import models
def render_user(user):
    return user

# ✅ Solution 2: Restructure into multiple modules
# interfaces.py
class UserBase:
    pass

# models.py
from .interfaces import UserBase

class User(UserBase):
    pass

# views.py
def render_user(user):
    return str(user)

Detecting circular imports:

import sys

def detect_circular_imports():
    """Find potential circular dependencies."""
    modules = sys.modules.copy()

    for name, module in modules.items():
        if module is None or not hasattr(module, "__dict__"):
            continue

        # Check module's __dict__ for imports
        for attr_name, attr_value in module.__dict__.items():
            if isinstance(attr_value, type(sys)):
                # This module imports another
                pass

💡 Type-Specific Imports

Import different implementations based on conditions.

# database.py - Conditional database imports

import sys

# Import based on installed packages
try:
    import psycopg2
    DATABASE_BACKEND = "postgresql"
except ImportError:
    try:
        import mysql.connector
        DATABASE_BACKEND = "mysql"
    except ImportError:
        import sqlite3
        DATABASE_BACKEND = "sqlite"

class Database:
    @classmethod
    def connect(cls, connection_string):
        if DATABASE_BACKEND == "postgresql":
            return psycopg2.connect(connection_string)
        elif DATABASE_BACKEND == "mysql":
            return mysql.connector.connect(connection_string)
        else:
            return sqlite3.connect(connection_string)

Version-specific imports:

import sys

# Import based on Python version
if sys.version_info >= (3, 10):
    from typing import ParamSpec  # Python 3.10+
else:
    from typing_extensions import ParamSpec  # Backport

# Use modern features when available
if sys.version_info >= (3, 9):
    from typing import Annotated  # Built-in in 3.9+
else:
    from typing_extensions import Annotated

🏗️ Module Monkey Patching

Safely modify modules at runtime.

# Original module: mymodule.py
def original_function():
    return "original"

# runtime_patches.py
import mymodule

# Store original
_original_function = mymodule.original_function

def patched_function():
    """Enhanced version of original function."""
    result = _original_function()
    return f"patched: {result}"

# Apply patch
mymodule.original_function = patched_function

# Now all code using mymodule gets patched version
result = mymodule.original_function()  # "patched: original"

Context manager for temporary patches:

from contextlib import contextmanager

@contextmanager
def patch_module(module, attr_name, value):
    """Temporarily patch module attribute."""
    old_value = getattr(module, attr_name)
    setattr(module, attr_name, value)
    try:
        yield
    finally:
        setattr(module, attr_name, old_value)

# Usage
import time

with patch_module(time, "sleep", lambda x: None):
    # time.sleep() does nothing in this block
    time.sleep(10)  # Instant!

# time.sleep() restored after block
time.sleep(0.1)  # Actually sleeps

📦 Dynamic Module Loading Patterns

Load modules dynamically based on configuration or discovery.

import importlib
import os
from pathlib import Path

class PluginLoader:
    """Load plugins from directory."""

    def __init__(self, plugin_dir):
        self.plugin_dir = Path(plugin_dir)
        self.plugins = {}

    def load_all(self):
        """Discover and load all plugins."""
        for py_file in self.plugin_dir.glob("*.py"):
            if not py_file.name.startswith("_"):
                self.load_plugin(py_file.stem)

    def load_plugin(self, name):
        """Load single plugin."""
        spec = importlib.util.spec_from_file_location(
            name,
            self.plugin_dir / f"{name}.py"
        )
        module = importlib.util.module_from_spec(spec)
        sys.modules[name] = module
        spec.loader.exec_module(module)
        self.plugins[name] = module
        return module

    def reload_plugin(self, name):
        """Reload plugin (useful in development)."""
        if name in sys.modules:
            del sys.modules[name]
        return self.load_plugin(name)

Configuration-driven imports:

import importlib
import json

# config.json
config = {
    "handlers": {
        "json": "handlers.json_handler",
        "csv": "handlers.csv_handler",
        "xml": "handlers.xml_handler"
    }
}

class HandlerFactory:
    """Load handlers from configuration."""

    @staticmethod
    def get_handler(format_type):
        """Load handler class based on format."""
        if format_type not in config["handlers"]:
            raise ValueError(f"Unknown format: {format_type}")

        module_path = config["handlers"][format_type]
        module_name, class_name = module_path.rsplit(".", 1)

        module = importlib.import_module(module_name)
        handler_class = getattr(module, class_name)
        return handler_class()

# Usage
handler = HandlerFactory.get_handler("json")

🔄 Import Optimization Techniques

import sys
import time
import importlib

class ImportOptimizer:
    """Analyze and optimize imports."""

    @staticmethod
    def measure_import_time(module_name):
        """Measure import time."""
        start = time.time()
        importlib.import_module(module_name)
        return time.time() - start

    @staticmethod
    def find_slow_imports(modules, threshold=0.1):
        """Find imports taking too long."""
        slow = []
        for module in modules:
            elapsed = ImportOptimizer.measure_import_time(module)
            if elapsed > threshold:
                slow.append((module, elapsed))
        return sorted(slow, key=lambda x: x[1], reverse=True)

    @staticmethod
    def optimize_startup():
        """Lazy import strategy."""
        # Fast built-in imports
        import sys
        import os

        # Defer heavy imports
        def get_numpy():
            return __import__("numpy")

        def get_pandas():
            return __import__("pandas")

        return {
            "numpy": get_numpy,
            "pandas": get_pandas
        }

# Usage
optimizer = ImportOptimizer()
slow = optimizer.find_slow_imports(["numpy", "pandas", "requests"])

💻 Advanced __init__.py Patterns

# Package __init__.py with advanced features

__version__ = "1.0.0"
__all__ = ["api", "models", "utils"]

# Lazy loading entire subpackages
def __getattr__(name):
    """Lazy import submodules."""
    if name == "api":
        from . import api
        return api
    elif name == "models":
        from . import models
        return models
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

def __dir__():
    """Support dir() on package."""
    return sorted(__all__)

# Conditional imports for optional features
try:
    from .database import Database
    HAS_DATABASE = True
except ImportError:
    HAS_DATABASE = False

# Configuration at package level
_config = {
    "debug": False,
    "version": __version__
}

def get_config():
    """Get package configuration."""
    return _config.copy()

🎨 Import Chain for Complex Dependencies

# Handle complex dependency chains

import importlib
from typing import Dict, List, Set

class DependencyResolver:
    """Resolve import dependencies."""

    def __init__(self):
        self.dependencies: Dict[str, Set[str]] = {}

    def add_dependency(self, module: str, depends_on: str):
        """Register module dependency."""
        if module not in self.dependencies:
            self.dependencies[module] = set()
        self.dependencies[module].add(depends_on)

    def load_in_order(self, target_module: str):
        """Load module with all dependencies."""
        to_load = self._topological_sort(target_module)
        loaded = {}

        for module in to_load:
            loaded[module] = importlib.import_module(module)

        return loaded

    def _topological_sort(self, module: str) -> List[str]:
        """Sort modules by dependency order."""
        visited = set()
        order = []

        def visit(m):
            if m in visited:
                return
            visited.add(m)

            if m in self.dependencies:
                for dep in self.dependencies[m]:
                    visit(dep)

            order.append(m)

        visit(module)
        return order

🔑 Key Takeaways

  • ✅ Resolve circular imports with late imports
  • ✅ Use conditional imports for version/platform support
  • ✅ Dynamic loading for plugin systems
  • ✅ Lazy imports reduce startup time
  • ✅ Monitor import performance
  • ✅ Use context managers for temporary patches
  • ✅ Design modular import chains for dependencies

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