In grpc-mate we have product_read_servicer.py to show how to output large binary stream via data chunk in grpc.

python-grpc

protobuf

rpc DownloadProductImage(DownloadProductImageRequest) returns(stream DataChunk){
}
message DownloadProductImageRequest {
    int64 product_id = 1;
}
message DataChunk {
    bytes data = 1;
}

Server Side

def DownloadProductImage(self, request, context):
    chunk_size = 1024
    image_path = Path(__file__).resolve().parent.parent.joinpath('images/python-grpc.png')

    with image_path.open('rb') as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            yield DataChunk(data=chunk)
  • it's recommended to use pathlib over os.path as it's follow the OO design, see details from this article
  • thanks to python's simple design, it's much simpler than the Java Version to stream binary files as stream, we just need to open the binary file in binary mode and read the data chunk by chunk, then just yield it, the grpc framework will take care all the other stuff

Client Side

def test_DownloadProductImage(grpc_stub):
    faker = Faker()
    target_image_file = faker.file_name(category=None, extension='png')
    data_chunks = grpc_stub.DownloadProductImage(DownloadProductImageRequest(product_id=1))
    with open(target_image_file, 'wb') as f:
        for chunk in data_chunks:
            f.write(chunk.data)

    original_image_file = Path(__file__).resolve().parent.parent.parent.joinpath('images/python-grpc.png')
    assert filecmp.cmp(original_image_file, target_image_file)
    os.remove(target_image_file)
  • first we create a fake image file path to save download image by python faker
  • then call the grpc service, it will return an iterator
  • next we could open the fake image file in write mode and iterator over the data chunk to save the image filee
  • after the fake image file is saved locally , we could use filecmp module to make sure the downloaded file is the same as original image file
  • finally we could delete the temp fake image file as a clean up.