Какую проблему решает библиотека Dependency Injector в Python?

Ответ

Библиотека dependency-injector реализует паттерн Внедрение зависимостей (Dependency Injection, DI) и помогает управлять Инверсией контроля (Inversion of Control, IoC) в Python-приложениях.

Основная проблема, которую она решает, — это жесткая связанность (tight coupling) компонентов. Вместо того чтобы компонент сам создавал свои зависимости (например, коннектор к базе данных или API-клиент), он получает их извне из специального контейнера.

Пример:

from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide

# 1. Определяем компоненты
class ApiClient:
    def __init__(self, api_key: str):
        self._api_key = api_key

class MyService:
    def __init__(self, client: ApiClient):
        self._client = client

# 2. Создаем контейнер для управления зависимостями
class Container(containers.DeclarativeContainer):
    config = providers.Configuration()

    # Провайдер Singleton гарантирует, что будет создан только один экземпляр ApiClient
    api_client = providers.Singleton(
        ApiClient,
        api_key=config.api.key
    )

    # Провайдер Factory будет создавать новый экземпляр MyService при каждом запросе
    my_service = providers.Factory(
        MyService,
        client=api_client
    )

# 3. Используем контейнер в приложении
@inject
def main(service: MyService = Provide[Container.my_service]):
    # ... здесь логика, использующая сервис
    pass

if __name__ == "__main__":
    container = Container()
    container.config.api.key.from_env("API_KEY", required=True)
    container.wire(modules=[__name__]) # Связываем контейнер с текущим модулем

    main()

Основные преимущества:

  • Слабая связанность (Loose Coupling): Компоненты не зависят от конкретных реализаций своих зависимостей.
  • Упрощение тестирования: В тестах легко подменить реальные зависимости (например, ApiClient) на мок-объекты.
  • Централизованная конфигурация: Все зависимости и их настройки собраны в одном месте — контейнере.