How to Build a Simple gRPC-Style Data Service in Python

Create a beginner-friendly gRPC-style service with dataclasses to simulate GetUser and CreateUser RPCs.

Easy Python 3.10+ Aug 9, 2026 API design & gRPC 13 views 0 copies

Python code

54 lines
Python 3.10+
from dataclasses import dataclass
from typing import Optional


@dataclass
class User:
    id: int
    name: str
    email: str


class UserService:
    """Simple gRPC-style service contract for beginner learners."""

    def get_user(self, user_id: int) -> Optional[User]:
        """Simulated gRPC GetUser RPC."""
        # Mock database
        users = {
            1: User(1, "Alice", "alice@example.com"),
            2: User(2, "Bob", "bob@example.com"),
        }
        return users.get(user_id)

    def create_user(self, name: str, email: str) -> User:
        """Simulated gRPC CreateUser RPC."""
        # In real gRPC, this would send a request to a server
        return User(id=3, name=name, email=email)


# gRPC-style message classes
@dataclass
class GetUserRequest:
    user_id: int


@dataclass
class UserResponse:
    user: Optional[User]


if __name__ == "__main__":
    service = UserService()

    # Demonstrate RPC-style calls
    request = GetUserRequest(user_id=1)
    response = UserResponse(user=service.get_user(request.user_id))
    print(f"GetUser(1) -> {response.user}")

    request = GetUserRequest(user_id=99)
    response = UserResponse(user=service.get_user(request.user_id))
    print(f"GetUser(99) -> {response.user}")

    new_user = service.create_user("Charlie", "charlie@example.com")
    print(f"CreateUser -> {new_user}")

Output

stdout
GetUser(1) -> User(id=1, name='Alice', email='alice@example.com')
GetUser(99) -> None
CreateUser -> User(id=3, name='Charlie', email='charlie@example.com')

How it works

This code uses Python dataclasses to model gRPC-style request/response messages and a service class to simulate RPC calls. The UserService acts as a stand-in for a gRPC server, with methods that mirror GetUser and CreateUser RPCs. Dataclasses simplify message definitions by auto-generating __init__, __repr__, and comparison methods. The Optional type hint indicates a method may return None when a user isn't found, mimicking how gRPC handles missing entities. This pattern helps beginners understand the structure of gRPC services without needing actual gRPC server infrastructure.

Common mistakes

  • Forgetting to use `Optional` for return types that can be `None`, causing type checker errors.
  • Hardcoding data in the service instead of using a real database or repository pattern.
  • Confusing dataclass fields with gRPC protobuf fields — this is only a simulation, not real gRPC.

Variations

  1. Add a proto file and use the `grpcio` package for real wire-format communication.
  2. Use `typing.Protocol` to define the service interface formally.

Real-world use cases

  • Prototyping the API contract of a gRPC service before wiring up the actual server.
  • Teaching new team members the request/response message pattern without infrastructure setup.
  • Mocking gRPC endpoints in unit tests for client-side services.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.