Im using dependency_injector in python with fastapi, and I’d like to cache instances of classes by the parameters passed to them. Here’s my current code:
from fastapi import FastAPI, Depends
from dependency_injector import containers, providers
from dependency_injector.providers import Factory
from dependency_injector.wiring import inject, Provide, Provider
class Service:
def __init__(self, name: str):
print(f"Called constructor for {name}")
self.name = name
def send_message(self) -> dict[str, str]:
return {"message": f"Hello, {self.name}"}
class Container(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(modules=[__name__])
service_factory = providers.Factory(Service)
def create_app() -> FastAPI:
app = FastAPI()
app.container = Container()
service_factory = app.container.service_factory
print(service_factory(name="World").send_message())
print(service_factory(name="Wirld").send_message())
print(service_factory(name="World").send_message())
return app
app = create_app()
# Define a simple route
@app.get("/hello/{name}")
@inject
async def hello(
name: str,
service_factory: Factory[Service] = Depends(Provide[Container.service_factory]),
):
print(type(service_factory))
service = service_factory(name=name)
return service.send_message()
In the following example, I have two problems:
-
In the create_app function, the container factory gets called twice for "World". (Using a providers.Singleton doesn’t work, the saved instance will be the first instance)
-
For some reason, in the /hello/{name} route, if I try to GET it service_factory is of type "Provide", and calling the service_factory(name=name) just throws an error saying that _Marker doesn’t expect arguments. I tried changing the WiringConfig to ".app" (current file name) but it still doesn’t work)
So I’d love this example to work without calling a constructor with the same arguments twice, and while still having type hinting
You need to sign in to view this answers
Leave feedback about this