Simple gRPC in Python

Overview

--Create a simple gRPC process in Python. --Try to create a process that requests some value and returns the result like REST.

Overall flow

  1. Install grpcio-tools
  2. Create a .proto file and compile it.
  3. Create server and client sources using the automatically generated sources.
  4. Test

1. Install grpcio-tools

Install with pip


$ pip install grpcio-tools

2. Create proto file

simple.proto


syntax = "proto3";

package simple;

// request
message SimpleRequest{
    string name = 1;
    string msg = 2;
}

// response
message SimpleResponse{
    string reply_msg = 1;
}

// interface
service SimpleService{
    rpc SimpleSend (SimpleRequest) returns (SimpleResponse) {}
}

Create and execute the following source. (compile) Simple_pb2.py and simple_pb2_grpc.py are created in the same folder.

codegen.py


from grpc.tools import protoc
protoc.main(
    (
        '',
        '-I.',
        '--python_out=.',
        '--grpc_python_out=.',
        'simple.proto',
    )
)

Run


$ python codegen.py

3. Source creation for server and client

Server side

server.py


import grpc
import time
import simple_pb2
import simple_pb2_grpc
from concurrent import futures


class SimpleServiceServicer(simple_pb2_grpc.SimpleServiceServicer):
    def __init__(self):
        pass

    def SimpleSend(self, request, context):
        print('logging: name {}, msg {}'.format(request.name, request.msg))
        #Match with Response in proto file
        return simple_pb2.SimpleResponse(
            reply_msg = 'Hello! ' + request.name + '. Your message is ' + request.msg
        )


# start server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
simple_pb2_grpc.add_SimpleServiceServicer_to_server(SimpleServiceServicer(), server)
server.add_insecure_port('[::]:5051')
server.start()
print('run server')

# wait
try:
    while True:
        time.sleep(3600)
except KeyboardInterrupt:
    # stop server
    server.stop(0)

--Source explanation --Match the class name with service (SimpleServie) + Servicer in the proto file. --Match the function name (SimpleSend) with rpc. Since it is a function name, snake case (simple_send) may be better for Python --Since SimpleResponse is defined in simple_pb2, response is returned from there.

Client side

client.py


import grpc
import simple_pb2
import simple_pb2_grpc


with grpc.insecure_channel('localhost:5051') as channel:
    stub = simple_pb2_grpc.SimpleServiceStub(channel)
    name = "Tom"
    msg = "Test"
    response = stub.SimpleSend(simple_pb2.SimpleRequest(name=name, msg=msg))

print('Reply: ', response.reply_msg)

--Source explanation --SimpleRequest takes name and msg as arguments. Image that is passed to it and generates a class --Calling the SimpleSend function of the stub and passing the generated class as an argument to it --Output reply_msg included in response

4. Test

start server


$ python server.py
run server

Client execution


$ python client.py
Reply:  Hello! Tom. Your message is Test

Process finished with exit code 0

Working folder (final form)

 C:\Users\grpc directory

2020/01/21  17:47    <DIR>          .
2020/01/21  17:47    <DIR>          ..
2020/01/21  17:45               327 client.py
2020/01/21  14:31               173 codegen.py
2020/01/21  17:47               851 server.py
2020/01/21  17:43               300 simple.proto
2020/01/21  17:43             4,212 simple_pb2.py
2020/01/21  17:43             1,342 simple_pb2_grpc.py

When using a list or dict

If you want to return the value of the list

.proto file


syntax = "proto3";

package simple;

// request
message SimpleRequest{
}

// response 
message SimpleResponse{
    repeated string msgs = 1;  //Use repeated
}

// interface
service SimpleService{
    rpc simple_send (SimpleRequest) returns (SimpleResponse) {}
}

Server side

Server that returns a list


import grpc
import time
import simple_iter_pb2
import simple_iter_pb2_grpc
from concurrent import futures


class SimpleServiceServicer(simple_iter_pb2_grpc.SimpleServiceServicer):
    def __init__(self):
        pass

    def simple_send(self, request, context):
        sample_data = ['message1', 'message2']
        return simple_iter_pb2.SimpleResponse(msgs=sample_data)  #Don't forget the list name


# start server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
simple_iter_pb2_grpc.add_SimpleServiceServicer_to_server(SimpleServiceServicer(), server)
server.add_insecure_port('[::]:5051')
server.start()
print('run server')

# wait
try:
    while True:
        time.sleep(3600)
except KeyboardInterrupt:
    # stop server
    server.stop(0)

If you want to return the value of dict

.proto file


syntax = "proto3";

package simple;

// request
message SimpleRequest{
}

// response
message SimpleResponse{
    map<string, string> msg = 1; //use map
}

// interface
service SimpleService{
    rpc simple_send (SimpleRequest) returns (SimpleResponse) {}
}

Server omitted

reference

The following articles were very helpful. There is a more detailed description.

-Inter-application communication with gRPC and Protocol Buffers / Python -Try bidirectional communication with gRPC in Python. -Implement API with gRPC (Go)

Recommended Posts

Simple gRPC in Python
Try gRPC in Python
Simple regression analysis in Python
Simple IRC client in python
First simple regression analysis in Python
Simple OAuth 2 in Python (urllib + oauthlib)
Implementing a simple algorithm in Python 2
Run a simple algorithm in Python
Simple gacha logic written in Python
Quadtree in Python --2
Python in optimization
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python
A simple HTTP client implemented in Python
Try drawing a simple animation in Python
Create a simple GUI app in Python
Write a simple greedy algorithm in Python
Write a simple Vim Plugin in Python 3
Sorted list in Python
Daily AtCoder # 36 in Python
Daily AtCoder # 2 in Python
Implement Enigma in python
Daily AtCoder # 32 in Python