How to write a gRPC client in Python for a gRPC service written in Java

Question:

I am not able to move forward with this confusion as I don’t know what to do. Most of the tutorials in Python get the main Class name where a method is defined, not sure how to do it when you just have to write the client.

Asked By: Ezio

||

Answers:

I suspect you’re a beginner or intermediate programmer, so I’d be very surprised if you’re tasked with or attempting something as complex as writing your own gRPC client. My guess is that you actually just want to read data from a Java gRPC service, and you’ve read about using a Python gRPC client, but you’re confused about how to do that.

Simplified example of a client.

First, let’s talk about how a client might work. Imagine writing a Python class like

class MyClient:
    def __init__(self, address, port):
        self.address = address
        self.port = port
        // create a grpc channel

    def connect(self):
        // connect the channel

    def read(self):
        // read the channel

Then in your main function you would create an instance of this client, using it to connect and read (or write) messages. So a client is just an object that does the dirty work of connecting to some place and reading messages off the wire for you.

The above is a poor example because that’s not really how gRPC works. I just figured a more traditional connect-and-read example would be easier to understand. Now you see the connection between your main function and a generic client.

So, how does gRPC fit into this?

The whole idea behind gRPC is that you don’t have to write a client. Look at it in steps like this:

  1. Someone began by writing a .proto file that "defined" their service. They defined what kinds of endpoints this service would have, e.g. getThings(), doThat().

  2. Then they used a program or plugin (grpc-java) to generate a mostly-finished Java application. The unfinished parts being: exactly what getThings() and doThat() does.

  3. They filled in that code… and done. grpc-java generated the whole server code for them, so their service is already up and running.

  4. Now you want to read from this service, but in Python.

  5. You just need to grab that same .proto file that they used to generate the Java service, and follow these steps to generate a client. So you see, just as they used a program to generate most of their Java service, you’re also going to use a program to generate a client for that service. (And not even "most." It generates a fully-functioning client.)

    python -m grpc_tools.protoc --python_out=. --grpc_python_out=. your_java_service_proto_file.proto
    
  6. In your main function, you just create an instance of that generated client (specifying an IP address and port to the Java service), and you’re good to go:

    channel = grpc.insecure_channel('10.123.123.123:54321')
    stub = the_generated_thing.RouteGuideStub(channel)
    things_from_java_service = stub.getThings()
    

A summary and another way of looking at it

Think of gRPC as a suite of programs written by https://grpc.io/ that generates code for everyone.

Someone defined a service in a .proto file then used one of those gRPC programs (grpc-java in your case) to generate most of a server. Then they implemented the rest and deployed that server.

Now, anyone like yourself can feed that same .proto file through another gRPC program (grpc-python in your case) to generate a fully functioning client in a language of your choice. You load up this generated client in your main function and you’re ready to interact with the server on the other side.

Answered By: Andrew Cheong