Search code examples
pythongrpc

Get the list of registered gRPC service name and methods in python


grpc-core for java has the option of getting a list of service descriptors from the grpc server object. From it we can gather the service name and method names.

    for (ServerServiceDefinition serverServiceDefinition: server.getServices()) {
        ServiceDescriptor serviceDescriptor = serverServiceDefinition.getServiceDescriptor();
        Collection<MethodDescriptor<?, ?>> methods = serviceDescriptor.getMethods();
        LOG.info("Service Name: {}", serviceDescriptor.getName());
        for (MethodDescriptor<?, ?> methodDescriptor : methods) {
            LOG.info("\t{}", methodDescriptor.getFullMethodName());
        }
    }

I am looking to achieve something similar in python, but is not as obvious. Ideally, I would like to do this without resorting to reflection, or hacking through the generated protobuf python files.

One way is to get the information from the protobuf files, but that would require more manual work:

    import service_pb2

    a = service_pb2._<service_name>
    print(a.name)
    for m in a.methods:
        print(f'\t{m.name}')

and it would make more sense to get the registered services through the server object itself.

For example, I would like to be able to output all the registered services and service methods associated to an application.

Server Name: ServiceName1
    serviceMethod1
    serviceMethod2
    serviceMethod3
    serviceMethod4
Server Name: ServiceName2
    serviceMethod1
    serviceMethod2
    serviceMethod3
Server Name: ServiceName3
    serviceMethod1
    serviceMethod2

Solution

  • If I understood your need correctly, the following snippet may help you.

    # server is the configured grpc server object.
    
    for service in server._state.generic_handlers:
        print("Service Name:", service.service_name())
        for method in service._method_handlers:
            print(4*" " + method)
    

    And if you didn't want the method's full name use this:

    method.split('/')[-1]