High-performance gRPC made simple. Write less, ship to production faster.
Development using gRPC made easy. Heavily inspired by FastAPI.
Important Disclaimer: In active development. Lock the package version and run your own tests.
🔥 Key Features
- Familiar, minimal API: an app object with a single decorator - @app.rpc("Service", "Method") - maps plain Python functions onto gRPC handlers, FastAPI-style.
- Zero protobuf boilerplate: .proto files are auto-discovered, compiled with protoc, and wired to your handlers at startup - no build step, no generated code to check in.
- FastAPI-style dependency injection: Depends() with nested dependency trees, caching-free depth-first resolution, and generator dependencies with pre/post teardown (yield), plus app-wide dependencies.
- Built-in injectables: handlers receive request, request_iterator, and context by parameter name - no protocol noise.
- Schemaless RPCs: @app.schemaless_rpc("Service", "Method") - build protobuf-free services over google.protobuf.Struct, sending and receiving plain dicts.
- Full streaming support: all four RPC flavors out of the box - unary, request-streaming, response-streaming, and bidirectional - response streams can yield messages or dicts.
- Typed exceptions for every gRPC status code: 16 concrete exceptions (NotFoundError, InvalidArgumentError, UnauthenticatedError, …) that auto-map to abort() on unary and streaming calls alike.
- First-class TLS/mTLS: ServerCredentials accepts paths or raw PEM, validates certificates fail-fast at startup, and supports client-auth.
- Hot-reload dev mode: app.dev() watches your .py and .proto files, recompiles and restarts on change - the gRPC developer loop FastAPI users expect.
- Production-grade logging out of the box: colorized access logs per RPC plus lifecycle/error loggers, configurable via LoggingConfig and honoring NO_COLOR.
- Full access to gRPC internals when you need them: pass interceptors, compression, channel options, xds, and concurrency limits straight through ServerOptions to grpc.server().
- Small and inspectable: Minimal abstraction, minimal dependencies, no magic you can't read.
⚙️ Installation
From pypi:
pip install simple-grpc
🚀 Quickstart
Server-side snippets: each one is a complete, runnable file (python server.py).
Schemaless endpoints
No proto files at all - plain dicts in, dicts out.
from simple_grpc import SimpleGRPC
app = SimpleGRPC(port=50051)
@app.schemaless_rpc("Greeter", "SayHello")
def say_hello(request):
return {"message": f"Hello, {request['name']}!"}
if __name__ == "__main__":
app.run()
Proto-backed endpoints
Pass proto content inline; it is compiled at startup into a generated-code directory under the system temp dir - no .proto file, no build step.
from simple_grpc import SimpleGRPC
CALCULATOR_PROTO = """
syntax = "proto3";
service Calculator {
rpc Add (AddRequest) returns (AddReply);
}
message AddRequest {
int64 a = 1;
int64 b = 2;
}
message AddReply {
int64 sum = 1;
}
"""
app = SimpleGRPC(raw_protos={"calculator": CALCULATOR_PROTO}, port=50052)
@app.rpc("Calculator", "Add")
def add(request):
return {"sum": request.a + request.b}
if __name__ == "__main__":
app.run()
Dependency injection
Declare Depends() in the handler signature. Plain dependencies resolve before the call; generator dependencies (yield) open and tear down around it.
from typing import Annotated
from simple_grpc import Depends, SimpleGRPC
app = SimpleGRPC(port=50053)
def auth_dep(context):
"""Read the bearer token from the metadata headers."""
metadata = dict(context.invocation_metadata())
if metadata.get("authorization") != "Bearer abc123":
context.abort(16, "unauthenticated")
return "alice"
UserDep = Annotated[str, Depends(auth_dep)]
def db_session():
"""Open a fake session for the handler and close it afterwards."""
print("db: session opened")
yield {"notes": ["shopping", "taxes"]}
print("db: session closed")
@app.schemaless_rpc("Notes", "GetNote")
def get_note(request, user: UserDep, db: Annotated[dict, Depends(db_session)]):
return {"user": user, "title": db["notes"][int(request["id"]) - 1]}
if __name__ == "__main__":
app.run()
During development, swap app.run() for app.dev() to hot-reload on file changes.
🧪 Tests
uv run pytest -vs
Metadata
Release files for simple-grpcio 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| simple_grpcio-0.1.5.tar.gz | 30.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| simple_grpcio-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.0 kB
Release files / simple_grpcio-0.1.5.tar.gz
| Download URL | simple_grpcio-0.1.5.tar.gz |
|---|---|
| Size | 30.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5d92cbb62bc599b938b21ab6b7b7d3279965fc96239911efec1ce9845aee95e
|
|
BLAKE2b-256 checksum How to use checksums |
e1d197b8774b3fa9c277d11063a162538fcd4be08398253bd482a2f88a5a9680
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.5
|
Release files / simple_grpcio-0.1.5-py3-none-any.whl
| Download URL | simple_grpcio-0.1.5-py3-none-any.whl |
|---|---|
| Size | 24.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
16e1c3289f414e7cc853e8393a7becbadd553adc6eb7e9d32674ca786b51fa4b
|
|
BLAKE2b-256 checksum How to use checksums |
86ceea620a16f4370f06abcc56b19f7326971bd596537329aae49e5a7f4502b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.5
|
Security for simple-grpcio 0.1.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.