Skip to main content

SimpleGRPC

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.

More examples...

🧪 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)

Source distribution for simple-grpcio 0.1.5
File Size Uploaded Provenance
simple_grpcio-0.1.5.tar.gz 30.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for simple-grpcio 0.1.5
File Interpreter ABI Platform
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.

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page