Skip to content

Commit 6a3b2fe

Browse files
committed
Add gRPC Python example with client/server implementation
Implements issue #4: add grpcio example Added: - grpcio-example.py: Complete client/server implementation - grpc_example.proto: Protocol Buffer service definition - GRPC_README.md: Comprehensive documentation and usage guide - grpcio>=1.68.0 and grpcio-tools>=1.68.0 dependencies Features: - Simple Greeter service with two RPC methods - Auto-generation of proto code via setup command - Support for custom host/port configuration - Clear usage instructions and examples Based on: https://grpc.io/docs/languages/python/quickstart/ Closes #4
1 parent 7b06e04 commit 6a3b2fe

File tree

5 files changed

+330
-0
lines changed

5 files changed

+330
-0
lines changed

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ dependencies = [
4343
"lxml>=5.2.0",
4444
"pillow>=10.3.0",
4545
"numpy>=1.26.0",
46+
"grpcio>=1.68.0",
47+
"grpcio-tools>=1.68.0",
4648
]
4749

4850
[tool.uv]

python-examples/GRPC_README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# gRPC Python Example
2+
3+
This example demonstrates a simple gRPC client-server application based on the [official Python quickstart guide](https://grpc.io/docs/languages/python/quickstart/).
4+
5+
## Overview
6+
7+
The example implements a `Greeter` service with two RPC methods:
8+
- `SayHello`: Returns a greeting message
9+
- `SayHelloAgain`: Returns another greeting message
10+
11+
## Files
12+
13+
- `grpc_example.proto` - Protocol Buffer definition file
14+
- `grpcio-example.py` - Complete client/server implementation
15+
16+
## Requirements
17+
18+
```bash
19+
pip install grpcio grpcio-tools
20+
```
21+
22+
## Setup
23+
24+
First, generate the gRPC Python code from the proto file:
25+
26+
```bash
27+
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. python-examples/grpc_example.proto
28+
```
29+
30+
Or use the built-in setup command:
31+
32+
```bash
33+
cd python-examples
34+
python grpcio-example.py setup
35+
```
36+
37+
This generates:
38+
- `grpc_example_pb2.py` - Protocol buffer message classes
39+
- `grpc_example_pb2_grpc.py` - gRPC service classes
40+
41+
## Running the Example
42+
43+
### Terminal 1 - Start the server
44+
45+
```bash
46+
cd python-examples
47+
python grpcio-example.py server
48+
```
49+
50+
Output:
51+
```
52+
✓ gRPC Server started on port 50051
53+
Waiting for client connections...
54+
Press Ctrl+C to stop
55+
```
56+
57+
### Terminal 2 - Run the client
58+
59+
```bash
60+
cd python-examples
61+
python grpcio-example.py client
62+
```
63+
64+
Output:
65+
```
66+
Connecting to gRPC server at localhost:50051...
67+
68+
1. Calling SayHello RPC...
69+
✓ Client received: Hello, World!
70+
71+
2. Calling SayHelloAgain RPC...
72+
✓ Client received: Hello again, gRPC User!
73+
74+
✓ All RPC calls completed successfully!
75+
```
76+
77+
## Custom Port
78+
79+
Start server on a different port:
80+
```bash
81+
python grpcio-example.py server 50052
82+
```
83+
84+
Connect client to custom port:
85+
```bash
86+
python grpcio-example.py client localhost 50052
87+
```
88+
89+
## Usage
90+
91+
```
92+
python grpcio-example.py setup - Generate proto files
93+
python grpcio-example.py server [port] - Start server (default: 50051)
94+
python grpcio-example.py client [host] [port] - Run client (default: localhost:50051)
95+
```
96+
97+
## Notes
98+
99+
- This example uses **insecure channels** for simplicity
100+
- In production, use secure channels with TLS/SSL certificates
101+
- The server runs indefinitely until Ctrl+C is pressed
102+
- Each client invocation makes two RPC calls and exits
103+
104+
## Learn More
105+
106+
- [gRPC Python Documentation](https://grpc.io/docs/languages/python/)
107+
- [Protocol Buffers](https://protobuf.dev/)
108+
- [gRPC Core Concepts](https://grpc.io/docs/what-is-grpc/core-concepts/)

python-examples/grpc_example.proto

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
syntax = "proto3";
2+
3+
package grpc_example;
4+
5+
// The greeting service definition.
6+
service Greeter {
7+
// Sends a greeting
8+
rpc SayHello (HelloRequest) returns (HelloReply) {}
9+
// Sends another greeting
10+
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
11+
}
12+
13+
// The request message containing the user's name.
14+
message HelloRequest {
15+
string name = 1;
16+
}
17+
18+
// The response message containing the greeting.
19+
message HelloReply {
20+
string message = 1;
21+
}

python-examples/grpcio-example.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!/usr/bin/env python3
2+
"""
3+
gRPC Python Example
4+
Based on: https://grpc.io/docs/languages/python/quickstart/
5+
6+
This example demonstrates a simple gRPC client-server application using
7+
the Greeter service from the official gRPC Python quickstart.
8+
9+
Requirements:
10+
pip install grpcio grpcio-tools
11+
12+
Setup:
13+
Before running, generate the gRPC Python code from the proto file:
14+
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. python-examples/grpc_example.proto
15+
16+
To run:
17+
1. Start the server: python grpcio-example.py server
18+
2. In another terminal, run the client: python grpcio-example.py client
19+
20+
Note: This example uses insecure channels for simplicity. In production,
21+
use secure channels with TLS/SSL certificates.
22+
"""
23+
24+
import sys
25+
import os
26+
import grpc
27+
from concurrent import futures
28+
import time
29+
import subprocess
30+
31+
# Check if proto files are generated, if not, generate them
32+
if not os.path.exists('python-examples/grpc_example_pb2.py'):
33+
print("Generating gRPC Python code from proto file...")
34+
try:
35+
subprocess.run([
36+
sys.executable, '-m', 'grpc_tools.protoc',
37+
'-I.', '--python_out=.', '--grpc_python_out=.',
38+
'python-examples/grpc_example.proto'
39+
], check=True)
40+
print("Generated successfully!\n")
41+
except subprocess.CalledProcessError as e:
42+
print(f"Error generating proto files: {e}")
43+
print("Make sure grpcio-tools is installed: pip install grpcio-tools")
44+
sys.exit(1)
45+
46+
# Import generated proto classes
47+
try:
48+
from python-examples import grpc_example_pb2
49+
from python-examples import grpc_example_pb2_grpc
50+
except ImportError:
51+
# Try alternative import path
52+
try:
53+
sys.path.insert(0, 'python-examples')
54+
import grpc_example_pb2
55+
import grpc_example_pb2_grpc
56+
except ImportError:
57+
print("Error: Failed to import generated gRPC modules.")
58+
print("Please ensure the proto files are generated correctly.")
59+
sys.exit(1)
60+
61+
62+
# Server implementation
63+
class Greeter(grpc_example_pb2_grpc.GreeterServicer):
64+
"""Implementation of the Greeter service."""
65+
66+
def SayHello(self, request, context):
67+
"""Responds to a HelloRequest with a HelloReply."""
68+
print(f"Server received: {request.name}")
69+
return grpc_example_pb2.HelloReply(message=f"Hello, {request.name}!")
70+
71+
def SayHelloAgain(self, request, context):
72+
"""Another greeting method."""
73+
print(f"Server received again: {request.name}")
74+
return grpc_example_pb2.HelloReply(message=f"Hello again, {request.name}!")
75+
76+
77+
def serve(port=50051):
78+
"""Start the gRPC server."""
79+
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
80+
grpc_example_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
81+
server.add_insecure_port(f'[::]:{port}')
82+
server.start()
83+
print(f"✓ gRPC Server started on port {port}")
84+
print(" Waiting for client connections...")
85+
print(" Press Ctrl+C to stop\n")
86+
87+
try:
88+
while True:
89+
time.sleep(86400) # One day
90+
except KeyboardInterrupt:
91+
print("\n\nShutting down server...")
92+
server.stop(0)
93+
print("Server stopped.")
94+
95+
96+
def run_client(host='localhost', port=50051):
97+
"""Run the gRPC client."""
98+
print(f"Connecting to gRPC server at {host}:{port}...")
99+
100+
# Create a channel
101+
with grpc.insecure_channel(f'{host}:{port}') as channel:
102+
# Create a stub (client)
103+
stub = grpc_example_pb2_grpc.GreeterStub(channel)
104+
105+
# Make a call to SayHello
106+
try:
107+
print("\n1. Calling SayHello RPC...")
108+
response = stub.SayHello(grpc_example_pb2.HelloRequest(name='World'))
109+
print(f" ✓ Client received: {response.message}")
110+
111+
# Make another call to SayHelloAgain
112+
print("\n2. Calling SayHelloAgain RPC...")
113+
response = stub.SayHelloAgain(grpc_example_pb2.HelloRequest(name='gRPC User'))
114+
print(f" ✓ Client received: {response.message}")
115+
116+
print("\n✓ All RPC calls completed successfully!\n")
117+
118+
except grpc.RpcError as e:
119+
print(f"\n✗ RPC failed: {e.code()} - {e.details()}\n")
120+
print(" Make sure the server is running: python grpcio-example.py server")
121+
sys.exit(1)
122+
123+
124+
def print_usage():
125+
"""Print usage instructions."""
126+
print("""
127+
gRPC Python Example
128+
===================
129+
130+
This demonstrates a basic gRPC client-server application based on the
131+
official Python quickstart guide.
132+
133+
Setup (first time only):
134+
Generate the gRPC Python code from the proto file:
135+
136+
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. python-examples/grpc_example.proto
137+
138+
Usage:
139+
python grpcio-example.py setup - Generate proto files
140+
python grpcio-example.py server [port] - Start the gRPC server (default: 50051)
141+
python grpcio-example.py client [host] [port] - Run the gRPC client
142+
143+
Examples:
144+
# Setup (only needed once)
145+
python grpcio-example.py setup
146+
147+
# Start server on default port
148+
python grpcio-example.py server
149+
150+
# Start server on custom port
151+
python grpcio-example.py server 50052
152+
153+
# Run client (connect to localhost:50051)
154+
python grpcio-example.py client
155+
156+
# Run client with custom host/port
157+
python grpcio-example.py client localhost 50052
158+
159+
Demo:
160+
Terminal 1: python grpcio-example.py server
161+
Terminal 2: python grpcio-example.py client
162+
""")
163+
164+
165+
if __name__ == '__main__':
166+
if len(sys.argv) < 2:
167+
print_usage()
168+
sys.exit(1)
169+
170+
command = sys.argv[1].lower()
171+
172+
if command == 'setup':
173+
print("Generating gRPC Python code from proto file...")
174+
try:
175+
subprocess.run([
176+
sys.executable, '-m', 'grpc_tools.protoc',
177+
'-I.', '--python_out=.', '--grpc_python_out=.',
178+
'python-examples/grpc_example.proto'
179+
], check=True)
180+
print("✓ Generated successfully!")
181+
print("\nYou can now run:")
182+
print(" python grpcio-example.py server")
183+
print(" python grpcio-example.py client")
184+
except subprocess.CalledProcessError as e:
185+
print(f"✗ Error generating proto files: {e}")
186+
sys.exit(1)
187+
elif command == 'server':
188+
port = int(sys.argv[2]) if len(sys.argv) > 2 else 50051
189+
serve(port)
190+
elif command == 'client':
191+
host = sys.argv[2] if len(sys.argv) > 2 else 'localhost'
192+
port = int(sys.argv[3]) if len(sys.argv) > 3 else 50051
193+
run_client(host, port)
194+
else:
195+
print(f"Unknown command: {command}")
196+
print_usage()
197+
sys.exit(1)

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ requests>=2.31.0
3131
lxml>=5.2.0
3232
pillow>=10.3.0
3333
numpy>=1.26.0
34+
grpcio>=1.68.0
35+
grpcio-tools>=1.68.0

0 commit comments

Comments
 (0)