[Python-es] Dichoso GRPC en Python
Miguel de Dios Matias
tres.14159 en gmail.com
Sab Mar 19 11:21:49 EDT 2022
Buenas.
Me estoy haciendo unos POC en python sobre GRPC porque un compa del
curro lo quiere meter.
Y ya casi tengo (después de mucho sufrimiento...me da que no tiene
muchs comunidad y esta medio abandonado GRPC salvo en Golang) todos
los posibles formas de comunicación.
Pero me queda la que el request sea un stream, bueno a medias, porque
sincrona (que se quede clavado el client.py enviando mensajes si) pero
asyncrona, naranjas de la china.
Mi último intento fallido es:
test.proto
---------------------------------------------------------
syntax = "proto3";
message Saludo {
string nombre = 1;
int32 segundo = 2;
}
message Respuesta {
string frase = 1;
int32 segundo = 2;
}
service Saluda {
// Sends a greeting
rpc buenosdias (stream Saludo) returns (stream Respuesta) {}
}
-----------------------------------------------------
client.py
-------------------------------------------------------
import grpc
from concurrent import futures
# Generate pb2 and bp2_grpc generated python files
# python3 -m grpc_tools.protoc --proto_path=. --python_out=.
--grpc_python_out=. ./*.proto
import test_service_pb2_grpc
import test_pb2
from datetime import datetime
from time import sleep
import asyncio
from uuid import uuid4
class MyIterator:
def __init__(self, start=0):
self.num = start
def __iter__(self):
return self
def __next__(self):
sleep(2)
nombre = uuid4()
print(nombre)
return test_pb2.Saludo(nombre=f'{nombre}',
segundo=datetime.now().second)
class AsyncIterator:
def __aiter__(self):
return self
async def __anext__(self):
await asyncio.sleep(2)
nombre = uuid4()
print(nombre)
return test_pb2.Saludo(nombre=f'{nombre}',
segundo=datetime.now().second)
if __name__ == '__main__':
print("TEST CLIENT GRPC")
server_uri = 'localhost:50053'
print(f"CONNECT TO: {server_uri}")
with grpc.insecure_channel(server_uri) as channel:
stub = test_service_pb2_grpc.SaludaStub(channel)
# ~ saludo = test_pb2.Saludo(nombre=f'{uuid4()}',
segundo=datetime.now().second)
# ~ stream_connection = stub.buenosdias(iter((saludo,saludo)))
stream_connection = stub.buenosdias(MyIterator())
for response in stream_connection:
response_dict = {k.name: getattr(response, k.name) for k
in response.DESCRIPTOR.fields}
print(f"CLIENTE RECEIVED: {response_dict}")
--------------------------------------------------------------------------------------
Con un iterador "sincrono" funciona pero se queda o llamando con un
iterador de 1 elemento puest también y solo se clava 1 vez pero si
meto:
stream_connection = stub.buenosdias(AsyncIterator())
Falla.
Saludos.
Más información sobre la lista de distribución Python-es