Dishka
Dishka is a lightweight and performant dependency injection framework for Python, designed to be framework-agnostic and support asynchronous operations and scopes. It leverages type hints for dependency resolution, aiming for a 'cute' and agreeable API. The current version is 1.9.1, and it maintains an active release cadence with frequent minor updates and bug fixes.
Common errors
-
TypeError: object is not a Provider
cause A class intended to define dependencies does not inherit from `dishka.Provider`.fixEnsure your dependency provider class inherits from `dishka.Provider`, e.g., `class MyProvider(Provider):`. -
dishka.exceptions.InvalidDependencyGraphError: Cannot find dependency for MyService
cause The requested type (e.g., `MyService`) or one of its dependencies cannot be found in the registered providers, or there's a circular dependency.fixVerify that all types required by `MyService` (and `MyService` itself) are provided by a `@provide` decorated method in your `Provider`s, and check for circular dependencies. -
ModuleNotFoundError: No module named 'dishka.integrations.fastapi'
cause You are attempting to use a Dishka integration (e.g., for FastAPI) without installing the necessary extra package.fixInstall Dishka with the required extra: `pip install dishka[fastapi]` (replace `fastapi` with your desired integration). -
dishka.exceptions.ScopeExitError: Cannot exit scope REQUEST: it is not the current active scope.
cause You are trying to exit a container scope that is not the most recently entered or active scope, often due to mismatched `async with` blocks.fixEnsure that container scopes are entered and exited in the correct LIFO (Last-In, First-Out) order, typically by nesting `async with container(scope=...)` blocks correctly.
Warnings
- gotcha Dishka's framework integrations (e.g., FastAPI, AioGram) require installing extra packages (e.g., `dishka[fastapi]`). Forgetting these will result in `ModuleNotFoundError` for integration-specific imports.
- gotcha Incorrect scope management, such as trying to exit a scope that isn't the current active one or accessing a shorter-lived dependency from a longer-lived scope, will lead to `ScopeExitError` or `InvalidDependencyGraphError`.
- gotcha Dishka relies heavily on accurate type hints for dependency resolution. Complex or ambiguous type hints (e.g., `Union`, `Annotated`, `Protocol`) can sometimes lead to `NotAFactoryError` or `UnsupportedAnnotationError` if not handled precisely.
Install
-
pip install dishka -
pip install dishka[fastapi] -
pip install dishka[aiogram] -
pip install dishka[litestar]
Imports
- Provider
from dishka import Provider
- Scope
from dishka import Scope
- provide
from dishka import provide
- inject
from dishka import inject
- make_container
from dishka import make_container
Quickstart
import asyncio
from dishka import Provider, Scope, provide, make_container
class MyDependency:
def __init__(self, name: str):
self.name = name
class MyService:
def __init__(self, dep: MyDependency):
self.dep = dep
class MyProvider(Provider):
@provide(scope=Scope.APP)
def get_dependency(self) -> MyDependency:
return MyDependency(name="Global Dep")
@provide(scope=Scope.REQUEST)
def get_service(self, dep: MyDependency) -> MyService:
return MyService(dep)
async def main():
# 1. Create a container with your providers
container = make_container(MyProvider())
# 2. Enter an application scope
async with container(scope=Scope.APP) as app_container:
# 3. Enter a request scope (or other child scope)
async with app_container(scope=Scope.REQUEST) as request_container:
# 4. Get a dependency from the current scope
service = await request_container.get(MyService)
print(f"Service created with dependency name: {service.dep.name}")
await container.close()
if __name__ == "__main__":
asyncio.run(main())