modern-di integration for gRPC (grpcio).
Full guide: gRPC integration docs
Usage example: examples/
Installation
uv add modern-di-grpc # or: pip install modern-di-grpc
Usage
gRPC has no dependency-injection system of its own, so modern-di-grpc pairs an @inject decorator with inert FromDI markers. A DIInterceptor (sync) or DIAioInterceptor (async) opens one Scope.REQUEST child container per RPC and resolves the FromDI-marked parameters of @inject-decorated servicer methods. Constructing the interceptor registers the ServicerContext provider on the container automatically; there is no separate setup call.
import typing
from concurrent import futures
import grpc
from modern_di import Container, Group, Scope, providers
from modern_di_grpc import DIInterceptor, FromDI, inject
from myapp import greeter_pb2, greeter_pb2_grpc # your generated stubs
class Settings:
def __init__(self) -> None:
self.greeting = "hello"
class Greeter:
def __init__(self, settings: Settings) -> None: # auto-injected by type
self._settings = settings
def greet(self, name: str) -> str:
return f"{self._settings.greeting}, {name}"
class AppGroup(Group):
settings = providers.Factory(Settings, scope=Scope.APP, cache=True)
greeter = providers.Factory(Greeter, scope=Scope.REQUEST)
class GreeterService(greeter_pb2_grpc.GreeterServicer):
@inject
def SayHello(
self,
request: greeter_pb2.HelloRequest,
context: grpc.ServicerContext,
greeter: typing.Annotated[Greeter, FromDI(Greeter)], # resolve by type
) -> greeter_pb2.HelloReply:
return greeter_pb2.HelloReply(message=greeter.greet(request.name))
container = Container(groups=[AppGroup])
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=10),
interceptors=[DIInterceptor(container)],
)
container.validate() # optional fail-fast; must come after DIInterceptor registers its providers
greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterService(), server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()
container.close_sync()
For an async server, pass DIAioInterceptor(container) to grpc.aio.server(...) and write async def servicer methods; @inject adapts to sync, async, and async-generator (server-streaming) methods across all four RPC types. A container is open from construction, so there is no .open() call before constructing the interceptor, and neither interceptor opens the root itself. Validation is explicit: call .validate() after constructing the interceptor if you want a broken graph to fail at start-up rather than at the first RPC that touches it. gRPC has no server startup or shutdown hook, so closing the root container is up to you: call close_sync() (or await close_async() on grpc.aio) after the server stops.
API
| Symbol | Description |
|---|---|
DIInterceptor(container) |
grpc.ServerInterceptor for the sync thread-pool server. Opens a Scope.REQUEST child per RPC (close_sync); auto-registers grpc_context_provider |
DIAioInterceptor(container) |
grpc.aio.ServerInterceptor for the async server. Same, with close_async |
FromDI(dependency) |
Inert marker for Annotated[T, FromDI(...)] in servicer-method signatures; accepts a provider instance or a type |
inject(method) |
Decorates a servicer method to resolve its FromDI parameters from the current RPC's child container; adapts to sync / async / async-generator methods |
fetch_di_container() |
Returns the current RPC's child container (raises RuntimeError outside an RPC) |
grpc_context_provider |
ContextProvider exposing grpc.ServicerContext at Scope.REQUEST; auto-registered by the interceptor |
📦 PyPI
📝 License
Part of modern-python
Built on modern-di, a dependency-injection framework with an IoC container and scopes.
Browse the full list of templates and libraries in
modern-python; the org profile has the categorized index.
Metadata
Release files for modern-di-grpc 4.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| modern_di_grpc-4.0.0.tar.gz | 6.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| modern_di_grpc-4.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.1 kB
Release files / modern_di_grpc-4.0.0.tar.gz
| Download URL | modern_di_grpc-4.0.0.tar.gz |
|---|---|
| Size | 6.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0d997b3b89a5ffcf7e5b2335414f89250a61580bfe74d47dd0cac910bc612971
|
|
BLAKE2b-256 checksum How to use checksums |
8dc890588e4d0df1a2f44ba2bd2fad5821b88e5f178add12065f13fc6bd5d38e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / modern_di_grpc-4.0.0-py3-none-any.whl
| Download URL | modern_di_grpc-4.0.0-py3-none-any.whl |
|---|---|
| Size | 6.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
55de27f2cbb6732c2349b0d81a5d6a003e1c4c559c292c3d8cf439e25598077c
|
|
BLAKE2b-256 checksum How to use checksums |
c49bfaa1f7e8e3e9923d0f5bd55cc5f0f3d4fa99f42bafea5af6dfee553f13c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|