Dependency injection framework for Python
—
Containers organize providers into cohesive units and manage the dependency graph. They provide functionality for provider registration, dependency wiring, resource lifecycle management, and configuration loading.
Foundation container class with core dependency management functionality.
class Container:
"""Base container class with provider management and dependency wiring."""
def __init__(self): ...
def __setattr__(self, name, value): ...
def __getattr__(self, name): ...
# Provider management
def set_providers(self, **providers): ...
def set_provider(self, name, provider): ...
# Container overriding
def override(self, overriding): ...
def reset_override(self): ...
# Dependency wiring
def wire(self, modules=None, packages=None, from_package=None): ...
def unwire(self): ...
# Resource lifecycle
def init_resources(self): ...
def shutdown_resources(self): ...
# Configuration loading
def load_config(self): ...
def from_schema(self, schema): ...
def from_yaml_schema(self, filepath, loader=None): ...
def from_json_schema(self, filepath): ...
# Singleton management
def reset_singletons(self): ...
# Dependency validation
def check_dependencies(self): ...
# Provider traversal
def traverse(self, types=None): ...Runtime container with dynamic provider registration capabilities.
class DynamicContainer(Container):
"""Runtime container with dynamic provider registration."""Usage example:
from dependency_injector import containers, providers
# Create dynamic container
container = containers.DynamicContainer()
# Add providers dynamically
container.set_providers(
database=providers.Singleton(Database, host="localhost"),
user_service=providers.Factory(UserService, database=container.database)
)
# Wire dependencies
container.wire(modules=[__name__])Class-based container definition with compile-time provider declarations.
class DeclarativeContainer(Container):
"""Class-based declarative container definition."""
def __init__(self, **overriding_providers): ...
@classmethod
def override(cls, overriding): ...
@classmethod
def override_providers(cls, **overriding_providers): ...
@classmethod
def reset_last_overriding(cls): ...
@classmethod
def reset_override(cls): ...Usage example:
from dependency_injector import containers, providers
class ApplicationContainer(containers.DeclarativeContainer):
# Configuration
config = providers.Configuration()
# Database
database = providers.Singleton(
Database,
host=config.database.host,
port=config.database.port,
username=config.database.username,
password=config.database.password,
)
# Services
user_repository = providers.Factory(
UserRepository,
database=database,
)
user_service = providers.Factory(
UserService,
repository=user_repository,
)
# Resources
redis_pool = providers.Resource(
RedisResource,
host=config.redis.host,
port=config.redis.port,
)
# Usage
container = ApplicationContainer()
container.config.from_yaml("config.yaml")
container.wire(modules=[__name__])Configuration class for specifying wiring behavior and target modules.
class WiringConfiguration:
"""Configuration for automatic dependency wiring."""
def __init__(
self,
modules=None,
packages=None,
from_package=None,
auto_wire=True,
keep_cache=False
): ...Usage example:
# Configure automatic wiring
class Container(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=["myapp.handlers", "myapp.services"],
packages=["myapp.web"],
auto_wire=True
)
# Providers...Mechanisms for overriding containers and providers for testing and environment-specific configuration.
# Base container
class BaseContainer(containers.DeclarativeContainer):
database = providers.Singleton(Database, host="localhost")
service = providers.Factory(Service, database=database)
# Test container with overrides
class TestContainer(containers.DeclarativeContainer):
database = providers.Singleton(MockDatabase)
# Override entire container
container = BaseContainer()
container.override(TestContainer)# Override specific providers
container = ApplicationContainer()
with container.override_providers(
database=providers.Singleton(TestDatabase),
user_service=providers.Singleton(MockUserService)
):
# Use container with overridden providers
service = container.user_service()Containers automatically manage resource initialization and cleanup.
# Initialize all resources in container
await container.init_resources()
# Shutdown all resources
await container.shutdown_resources()
# Context manager for resource lifecycle
async with container:
# Container resources are initialized
service = container.user_service()
result = await service.process()
# Resources are automatically shut downContainers can load configuration from multiple sources and formats.
class Container(containers.DeclarativeContainer):
config = providers.Configuration()
# Load configuration
container = Container()
# From YAML file
container.config.from_yaml("config.yaml")
# From environment variables
container.config.database.host.from_env("DB_HOST", default="localhost")
container.config.database.port.from_env("DB_PORT", as_=int, default=5432)
# From dictionary
container.config.from_dict({
"database": {"url": "postgresql://localhost/mydb"},
"redis": {"host": "localhost", "port": 6379}
})
# From JSON schema
container.from_json_schema("schema.json")Containers can validate dependency graphs and detect circular dependencies.
# Check for dependency issues
try:
container.check_dependencies()
except Exception as e:
print(f"Dependency error: {e}")Traverse and inspect the provider graph within containers.
# Find all singleton providers
singletons = list(container.traverse(types=[providers.Singleton]))
# Find all resource providers
resources = list(container.traverse(types=[providers.Resource]))
# Custom traversal
for provider in container.traverse():
print(f"Provider: {provider}")Context managers for scoped operations and resource management.
class ProvidersOverridingContext:
"""Context manager for provider overriding."""
def __enter__(self): ...
def __exit__(self, *exc_info): ...
class SingletonResetContext:
"""Context manager for singleton reset."""
def __enter__(self): ...
def __exit__(self, *exc_info): ...Usage example:
# Temporary provider overriding
with container.override_providers(
database=providers.Singleton(TestDatabase)
):
# Use overridden providers
pass
# Temporary singleton reset
with container.reset_singletons():
# Fresh singleton instances
passHelper functions for working with containers.
def override(container):
"""Decorator for container overriding."""
def copy(container):
"""Decorator for container copying."""
def is_container(instance) -> bool:
"""Check if object is a container."""Usage example:
# Container override decorator
@containers.override(BaseContainer)
class TestContainer(containers.DeclarativeContainer):
database = providers.Singleton(MockDatabase)
# Container copy decorator
@containers.copy(BaseContainer)
class DevelopmentContainer(containers.DeclarativeContainer):
# Inherits all providers from BaseContainer
# Can add or override specific providers
debug = providers.Object(True)Install with Tessl CLI
npx tessl i tessl/pypi-dependency-injector