See the full example here
Dubbo-Python supports streaming calls, including ClientStream, ServerStream, and BidirectionalStream modes.
Streaming calls can be divided into write-streams and read-streams. For ClientStream, it’s multiple writes with a single read; for ServerStream, a single write with multiple reads; and BidirectionalStream allows multiple writes and reads.
Write operations in streaming calls can be divided into single write (ServerStream) and multiple writes (ClientStream and BidirectionalStream).
Single write calls are similar to unary mode. For example:
stub.server_stream(greeter_pb2.GreeterRequest(name="hello world from dubbo-python"))
For multiple writes, users can write data using either an iterator or writeStream (only one of these options should be used).
Iterator-based Write: Writing via iterator is similar to unary mode, with the main difference being the use of an iterator for multiple writes. For example:
# Use an iterator to send multiple requests
def request_generator():
for i in ["hello", "world", "from", "dubbo-python"]:
yield greeter_pb2.GreeterRequest(name=str(i))
# Call the remote method and return a read_stream
stream = stub.client_stream(request_generator())
Using writeStream: This method requires an empty argument, after which data is written incrementally using write, and done_writing is called to end the write-stream. For example:
stream = stub.bi_stream()
# Use the write method to send messages
stream.write(greeter_pb2.GreeterRequest(name="jock"))
stream.write(greeter_pb2.GreeterRequest(name="jane"))
stream.write(greeter_pb2.GreeterRequest(name="alice"))
stream.write(greeter_pb2.GreeterRequest(name="dave"))
# Call done_writing to notify the server that the client has finished writing
stream.done_writing()
Read operations for streaming calls can be single read (ClientStream) or multiple reads (ServerStream and BidirectionalStream). A ReadStream is returned in all cases, and data can be read using the read method or an iterator. When using read, please note:
read method supports a timeout parameter (in seconds).read method can return one of three values: the expected data, None (timeout exceeded), or EOF (end of the read-stream).A single call to the read method will retrieve the data, for example:
result = stream.read()
print(f"Received response: {result.message}")
Multiple reads can be done by repeatedly calling read, with handling for None and EOF values. Since ReadStream implements __iter__ and __next__, an iterator-based approach can also be used, which automatically handles these values but doesn’t support a timeout.
Using Iterator (Recommended):
def client_stream(self, request_iterator):
response = ""
for request in request_iterator:
print(f"Received request: {request.name}")
response += f"{request.name} "
return greeter_pb2.GreeterReply(message=response)
Multiple Calls to read Method:
# Use read method to receive messages
# If no message arrives within the specified time, returns None
# If the server has finished sending messages, returns EOF
while True:
i = stream.read(timeout=0.5)
if i is dubbo.classes.EOF:
break
elif i is None:
print("No message received")
continue
print(f"Received response: {i.message}")