Grpc stream example python

Quick start

This guide gets you started with gRPC in Python with a simple working example.

Quick start

Prerequisites

If necessary, upgrade your version of pip :

$ python -m pip install --upgrade pip 

If you cannot upgrade pip due to a system-owned installation, you can run the example in a virtualenv:

$ python -m pip install virtualenv $ virtualenv venv $ source venv/bin/activate $ python -m pip install --upgrade pip 

gRPC

$ python -m pip install grpcio 

Or, to install it system wide:

$ sudo python -m pip install grpcio 

gRPC tools

Python’s gRPC tools include the protocol buffer compiler protoc and the special plugin for generating server and client code from .proto service definitions. For the first part of our quick-start example, we’ve already generated the server and client stubs from helloworld.proto , but you’ll need the tools for the rest of our quick start, as well as later tutorials and your own projects.

To install gRPC tools, run:

$ python -m pip install grpcio-tools 

Download the example

You’ll need a local copy of the example code to work through this quick start. Download the example code from our GitHub repository (the following command clones the entire repository, but you just need the examples for this quick start and other tutorials):

# Clone the repository to get the example code: $ git clone -b v1.56.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc # Navigate to the "hello, world" Python example: $ cd grpc/examples/python/helloworld 

Run a gRPC application

From the examples/python/helloworld directory:

Читайте также:  HTML

Congratulations! You’ve just run a client-server application with gRPC.

Update the gRPC service

Now let’s look at how to update the application with an extra method on the server for the client to call. Our gRPC service is defined using protocol buffers; you can find out lots more about how to define a service in a .proto file in Introduction to gRPC and Basics tutorial. For now all you need to know is that both the server and the client “stub” have a SayHello RPC method that takes a HelloRequest parameter from the client and returns a HelloReply from the server, and that this method is defined like this:

// The greeting service definition.  service Greeter  // Sends a greeting  rpc SayHello (HelloRequest) returns (HelloReply) <>  >   // The request message containing the user's name.  message HelloRequest  string name = 1;  >   // The response message containing the greetings  message HelloReply  string message = 1;  > 

Let’s update this so that the Greeter service has two methods. Edit examples/protos/helloworld.proto and update it with a new SayHelloAgain method, with the same request and response types:

// The greeting service definition.  service Greeter  // Sends a greeting  rpc SayHello (HelloRequest) returns (HelloReply) <>  // Sends another greeting  rpc SayHelloAgain (HelloRequest) returns (HelloReply) <>  >   // The request message containing the user's name.  message HelloRequest  string name = 1;  >   // The response message containing the greetings  message HelloReply  string message = 1;  > 

Remember to save the file!

Generate gRPC code

Next we need to update the gRPC code used by our application to use the new service definition.

From the examples/python/helloworld directory, run:

$ python -m grpc_tools.protoc -I../../protos --python_out=. --pyi_out=. --grpc_python_out=. ../../protos/helloworld.proto 

This regenerates helloworld_pb2.py which contains our generated request and response classes and helloworld_pb2_grpc.py which contains our generated client and server classes.

Update and run the application

We now have new generated server and client code, but we still need to implement and call the new method in the human-written parts of our example application.

Update the server

In the same directory, open greeter_server.py . Implement the new method like this:

class Greeter(helloworld_pb2_grpc.GreeterServicer):   def SayHello(self, request, context):  return helloworld_pb2.HelloReply(message=f'Hello, request.name>!')   def SayHelloAgain(self, request, context):  return helloworld_pb2.HelloReply(message=f'Hello again, request.name>!') . 

Update the client

In the same directory, open greeter_client.py . Call the new method like this:

def run():  with grpc.insecure_channel('localhost:50051') as channel:  stub = helloworld_pb2_grpc.GreeterStub(channel)  response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))  print("Greeter client received: " + response.message)  response = stub.SayHelloAgain(helloworld_pb2.HelloRequest(name='you'))  print("Greeter client received: " + response.message) 

Run!

Just like we did before, from the examples/python/helloworld directory:

What’s next

Источник

How to implement bi-directional streaming using gRPC with Python (Server) – Part 1

In our previous tutorials, we have demonstrated how to implement bi-directional streaming using NodeJS. Since gRPC is just a protocol definition so it can be implemented in any possible language. So today we will demonstrate how to setup a bi-directional server using python & gRPC.

The codebase has been shared on GitHub for your convenience as follows: https://github.com/techunits/bidirectional-streaming-grpc-sample-python

In order to execute the gRPC streaming, we will need the following pip libraries as pre-requisites:

grpcio==1.39.0 grpcio-tools==1.39.0 protobuf==3.17.3 six==1.16.0 uuid==1.30

The very first step to setup any gRPC communication is to create a data contract in the form of a protocol buffer file. In our demonstration, we will use a simple contract that should be able to create some resource entries to the server in the stream and expect a response in the form of a stream.

Our proto file as follows:

syntax = "proto3"; package SamplePackage; message EntryCreateRequest < string title = 1; string code = 2; string description = 3; >message EntryResponse < string string title = 2; string code = 3; string description = 4; int32 created_on = 6; >service SampleService < rpc createBulkEntries(stream EntryCreateRequest) returns (stream EntryResponse) <>>

Unlike NodeJS, python classes will not able to read the proto files directly, so we have to convert the proto into native python classes. The following command will generate 2 python class files sample_pb2_grpc.py & sample_pb2.py.

python -m grpc_tools.protoc -I./proto --python_out=./proto/ --grpc_python_out=./proto/ ./proto/sample.proto

gRPC Streaming Server:

Now we will define our server process which will read the above classes and servicer as follows:

# import required libraries & proto defn. import grpc from concurrent import futures from proto import sample_pb2_grpc # import servicer from servicers import SampleServiceServicer def serve(): # initialize server with 4 workers server = grpc.server(futures.ThreadPoolExecutor(max_workers=4)) # attach servicer method to the server sample_pb2_grpc.add_SampleServiceServicer_to_server(SampleServiceServicer(), server) # start the server on the port 50051 server.add_insecure_port("0.0.0.0:50051") server.start() print("Started gRPC server: 0.0.0.0:50051") # server loop to keep the process running server.wait_for_termination() # invoke the server method if __name__ == "__main__": serve()

The server process is having a dependency on the servicer method SampleServiceServicer defined as follows:

# import required libraries & proto defn. from proto import sample_pb2_grpc, sample_pb2 import uuid from datetime import datetime class SampleServiceServicer(sample_pb2_grpc.SampleServiceServicer): ''' this servicer method will read the request from the iterator supplied by incoming stream and send back the response in a stream ''' def createBulkEntries(self, request_iterator, context): entry_info = dict() for request in request_iterator: print(request) ##### save to database ##### # simulate the response after saving to database entry_info = < "id": str(uuid.uuid4()), "title": request.title, "code": request.code, "description": request.description, "created_on": round(datetime.now().timestamp()) ># stream the response back yield sample_pb2.EntryResponse(**entry_info) 

Once we are done with the above steps, we should be able to start the server with the following command:

$ python serve.py Started gRPC server: 0.0.0.0:50051

While building the server script we have using sConnector to test and debug our script visually even before creating any client. This helps a lot for a faster development cycle. Screenshot as follows:

gRPC Streaming Client:

In our next tutorial, we will explain how to implement a client to connect to the streaming server and send/receive the data as follows:

Источник

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Chat application created with gRPC. This was a study for bidirectional gRPC streaming.

melledijkstra/python-grpc-chat

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

Chat application created with gRPC. This was a study for bidirectional gRPC streaming.

Chat System

class ChatServer(rpc.ChatServerServicer): def __init__(self): # List with all the chat history self.chats = [] # The stream which will be used to send new messages to clients def ChatStream(self, request_iterator, context): """ This is a response-stream type call. This means the server can keep sending messages Every client opens this connection and waits for server to send new messages :param request_iterator: :param context: :return: """ lastindex = 0 # For every client a infinite loop starts (in gRPC's own managed thread) while True: # Check if there are any new messages while len(self.chats) > lastindex: n = self.chats[lastindex] lastindex += 1 yield n def SendNote(self, request: chat.Note, context): """ This method is called when a clients sends a Note to the server. :param request: :param context: :return: """ print("[<>] <>".format(request.name, request.message)) # Add it to the chat history self.chats.append(request) return chat.Empty()
address = 'localhost' port = 11912 class Client: def __init__(self, u: str, window): # the frame to put ui components on self.window = window self.username = u # create a gRPC channel + stub channel = grpc.insecure_channel(address + ':' + str(port)) self.conn = rpc.ChatServerStub(channel) # create new listening thread for when new message streams come in threading.Thread(target=self.__listen_for_messages, daemon=True).start() self.__setup_ui() self.window.mainloop() def __listen_for_messages(self): """ This method will be ran in a separate thread as the main/ui thread, because the for-in call is blocking when waiting for new messages """ for note in self.conn.ChatStream(chat.Empty()): print("R[<>] <>".format(note.name, note.message)) self.chat_list.insert(END, "[<>] <>\n".format(note.name, note.message)) def send_message(self, event): """ This method is called when user enters something into the textbox """ message = self.entry_message.get() if message is not '': n = chat.Note() n.name = self.username n.message = message print("S[<>] <>".format(n.name, n.message)) self.conn.SendNote(n) .
syntax = "proto3"; package grpc; message Empty <> // I called it Note because message Message is annoying to work with message Note < string name = 1; string message = 2; > service ChatServer < // This bi-directional stream makes it possible to send and receive Notes between 2 persons rpc ChatStream (Empty) returns (stream Note); rpc SendNote (Note) returns (Empty); >

About

Chat application created with gRPC. This was a study for bidirectional gRPC streaming.

Источник

Оцените статью