I am writing a GRPC python client to communicate with a GRPC server as below.
class GrpcClient:
"""
Class to send request to Grpc server.
"""
def __init__(self, host: str, port: int):
self._server_address = host + ':' + str(port)
with grpc.insecure_channel(self._server_address) as channel:
self._stub = MyServerStub(channel)
def invoke_method(self, request):
response = self._stub.process(request)
logging.info("response received: " + str(response))
This result in error ValueError: Cannot invoke RPC on closed channel! since the channel was getting closed on int I modified as below
def __init__(self, host: str, port: int):
self._server_address = host + ':' + str(port)
channel = grpc.insecure_channel(self._server_address)
self._stub = MyServerStub(channel)
Now both the channel and stub gets reused but my worry is that the channel might not be closed which might lead into memory leak
To prevent it I tried opening the channel and creating stub on each request which is expensive.
Can anyone suggest a way of reusing channel and stub without any leak?
There are two ways you could tackle this problem, which are not necessarily mutually exclusive. The first is proxying the channel's
close
method to your class and requiring your class's user to call it. That would look something like this:To make this API a bit cleaner, you could provide a context manager API similar to what
grpc.Channel
does:Then you can use your class like
People have attempted to use
__del__
to automatically call such cleanup methods in the past, but we've found that the guarantees provided by CPython about when and if this method will be called are too weak to provide anything resembling C++ RAII, so we're left with manual options like I outlined above.