Python Generated Code Reference

Introduction

gRPC Python relies on the protocol buffers compiler (protoc) to generatecode. It uses a plugin to supplement the generated code by plain protocwith gRPC-specific code. For a .proto service description containinggRPC services, the plain protoc generated code is synthesized ina _pb2.py file, and the gRPC-specifc code lands in a _grpc_pb2.py file.The latter python module imports the former. In this guide, we focuson the gRPC-specific subset of the generated code.

Illustrative Example

Let’s look at the following FortuneTeller proto service:

  1. service FortuneTeller {
  2. // Returns the horoscope and zodiac sign for the given month and day.
  3. rpc TellFortune(HoroscopeRequest) returns (HoroscopeResponse) {
  4. // errors: invalid month or day, fortune unavailable
  5. }
  6. // Replaces the fortune for the given zodiac sign with the provided one.
  7. rpc SuggestFortune(SuggestionRequest) returns (SuggestionResponse) {
  8. // errors: invalid zodiac sign
  9. }
  10. }

gRPC protoc plugin will synthesize code elements along the linesof what follows in the corresponding _pb2_grpc.py file:

  1. import grpc
  2. import fortune_pb2
  3. class FortuneTellerStub(object):
  4. def __init__(self, channel):
  5. """Constructor.
  6. Args:
  7. channel: A grpc.Channel.
  8. """
  9. self.TellFortune = channel.unary_unary(
  10. '/example.FortuneTeller/TellFortune',
  11. request_serializer=fortune_pb2.HoroscopeRequest.SerializeToString,
  12. response_deserializer=fortune_pb2.HoroscopeResponse.FromString,
  13. )
  14. self.SuggestFortune = channel.unary_unary(
  15. '/example.FortuneTeller/SuggestFortune',
  16. request_serializer=fortune_pb2.SuggestionRequest.SerializeToString,
  17. response_deserializer=fortune_pb2.SuggestionResponse.FromString,
  18. )
  19. class FortuneTellerServicer(object):
  20. def TellFortune(self, request, context):
  21. """Returns the horoscope and zodiac sign for the given month and day.
  22. errors: invalid month or day, fortune unavailable
  23. """
  24. context.set_code(grpc.StatusCode.UNIMPLEMENTED)
  25. context.set_details('Method not implemented!')
  26. raise NotImplementedError('Method not implemented!')
  27. def SuggestFortune(self, request, context):
  28. """Replaces the fortune for the given zodiac sign with the provided
  29. one.
  30. errors: invalid zodiac sign
  31. """
  32. context.set_code(grpc.StatusCode.UNIMPLEMENTED)
  33. context.set_details('Method not implemented!')
  34. raise NotImplementedError('Method not implemented!')
  35. def add_FortuneTellerServicer_to_server(servicer, server):
  36. rpc_method_handlers = {
  37. 'TellFortune': grpc.unary_unary_rpc_method_handler(
  38. servicer.TellFortune,
  39. request_deserializer=fortune_pb2.HoroscopeRequest.FromString,
  40. response_serializer=fortune_pb2.HoroscopeResponse.SerializeToString,
  41. ),
  42. 'SuggestFortune': grpc.unary_unary_rpc_method_handler(
  43. servicer.SuggestFortune,
  44. request_deserializer=fortune_pb2.SuggestionRequest.FromString,
  45. response_serializer=fortune_pb2.SuggestionResponse.SerializeToString,
  46. ),
  47. }
  48. generic_handler = grpc.method_handlers_generic_handler(
  49. 'example.FortuneTeller', rpc_method_handlers)
  50. server.add_generic_rpc_handlers((generic_handler,))

Code Elements

The gRPC generated code starts by importing the grpc package and the plain_pb2 module, synthesized by protoc, which defines non-gRPC-specifc codeelements, like the classes corresponding to protocol buffers messages anddescriptors used by reflection.

For each service Foo in the .proto file, three primary elements aregenerated:

  • Stub: FooStub used by the client to connect to a gRPC service.
  • Servicer: FooServicer used by the server to implement agRPC service.
  • Registration Function:add_FooServicer_to_server function used to register a servicer with agrpc.Server object.

Stub

The generated Stub class is used by the gRPC clients. Itwill have a constructor that takes a grpc.Channel object and initializes thestub. For each method in the service, the initializer adds a correspondingattribute to the stub object with the same name. Depending on the RPC type(i.e. unary or streaming), the value of that attribute will be callableobjects of typeUnaryUnaryMultiCallable,UnaryStreamMultiCallable,StreamUnaryMultiCallable,orStreamStreamMultiCallable.

Servicer

For each service, a Servicer class is generated. Thisclass is intended to serve as the superclass of a service implementation. Foreach method in the service, a corresponding function in the Servicer classwill be synthesized which is intended to be overriden in the actual serviceimplementation. Comments associated with code elementsin the .proto file will be transferred over as docstrings inthe generated python code.

Registration Function

For each service, a function will begenerated that registers a Servicer object implementing it on a grpc.Serverobject, so that the server would be able to appropriately route the queries tothe respective servicer. This function takes an object that implements theServicer, typically an instance of a subclass of the generated Servicercode element described above, and agrpc.Serverobject.