当前位置: 首页 > 工具软件 > Python grpc > 使用案例 >

Python gRPC 生成代码参考

周鸿光
2023-12-01

gRPC Python 依赖于协议缓冲区编译器 ( protoc) 来生成代码。protoc 它使用一个插件来通过纯gRPC 特定代码来补充生成的代码。对于.proto包含 gRPC 服务的服务描述,protoc生成的纯代码在一个_pb2.py文件中合成,而 gRPC 特定的代码位于一个_pb2_grpc.py文件中。后一个 python 模块导入了前者。此页面的重点是生成代码的特定于 gRPC 的子集。

例子
考虑以下FortuneTeller原型服务:

service FortuneTeller {
  // Returns the horoscope and zodiac sign for the given month and day.
  rpc TellFortune(HoroscopeRequest) returns (HoroscopeResponse) {
    // errors: invalid month or day, fortune unavailable
  }

  // Replaces the fortune for the given zodiac sign with the provided one.
  rpc SuggestFortune(SuggestionRequest) returns (SuggestionResponse) {
    // errors: invalid zodiac sign
  }
}

编译服务时,gRPCprotoc插件会生成类似于以下_pb2_grpc.py文件的代码:

import grpc

import fortune_pb2

class FortuneTellerStub(object):

  def __init__(self, channel):
    """Constructor.

    Args:
      channel: A grpc.Channel.
    """
    self.TellFortune = channel.unary_unary(
        '/example.FortuneTeller/TellFortune',
        request_serializer=fortune_pb2.HoroscopeRequest.SerializeToString,
        response_deserializer=fortune_pb2.HoroscopeResponse.FromString,
        )
    self.SuggestFortune = channel.unary_unary(
        '/example.FortuneTeller/SuggestFortune',
        request_serializer=fortune_pb2.SuggestionRequest.SerializeToString,
        response_deserializer=fortune_pb2.SuggestionResponse.FromString,
        )


class FortuneTellerServicer(object):

  def TellFortune(self, request, context):
    """Returns the horoscope and zodiac sign for the given month and day.
    errors: invalid month or day, fortune unavailable
    """
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')

  def SuggestFortune(self, request, context):
    """Replaces the fortune for the given zodiac sign with the provided
one.
    errors: invalid zodiac sign
    """
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')


def add_FortuneTellerServicer_to_server(servicer, server):
  rpc_method_handlers = {
      'TellFortune': grpc.unary_unary_rpc_method_handler(
          servicer.TellFortune,
          request_deserializer=fortune_pb2.HoroscopeRequest.FromString,
          response_serializer=fortune_pb2.HoroscopeResponse.SerializeToString,
      ),
      'SuggestFortune': grpc.unary_unary_rpc_method_handler(
          servicer.SuggestFortune,
          request_deserializer=fortune_pb2.SuggestionRequest.FromString,
          response_serializer=fortune_pb2.SuggestionResponse.SerializeToString,
      ),
  }
  generic_handler = grpc.method_handlers_generic_handler(
      'example.FortuneTeller', rpc_method_handlers)
  server.add_generic_rpc_handlers((generic_handler,))

代码元素
gRPC 生成的代码首先导入grpc包和由 _pb2合成的普通模块,protoc它定义了非 gRPC 特定的代码元素,例如对应于协议缓冲区消息的类和反射使用的描述符。

对于文件中的每个服务Foo,都会.proto生成三个主要元素:

Stub:FooStub客户端用来连接到 gRPC 服务。
Servicer:FooServicer由服务器用来实现 gRPC 服务。
注册函数: add_FooServicer_to_server用于向 grpc.Server对象注册服务者的函数。
存根
生成的Stub类由 gRPC 客户端使用。它有一个构造函数,它接受一个grpc.Channel对象并初始化存根。对于服务中的每个方法,初始化程序都会将相应的属性添加到具有相同名称的存根对象中。根据 RPC 类型(一元或流),该属性的值将是 UnaryUnaryMultiCallable、 UnaryStreamMultiCallable、 StreamUnaryMultiCallable或 StreamStreamMultiCallable类型的可调用对象。

服务商
对于每个服务,Servicer都会生成一个类,该类作为服务实现的超类。对于服务中的每个方法,都会在Servicer类中生成一个对应的函数。使用服务实现覆盖此函数。与文件中的代码元素关联的注释.proto在生成的 python 代码中显示为文档字符串。

注册功能
对于每个服务,都会生成一个函数,该函数在对象上注册Servicer实现它的grpc.Server 对象,以便服务器可以将查询路由到相应的服务程序。此函数采用实现 的对象 Servicer,通常是上述生成Servicer 代码元素的子类的实例,以及 grpc.Server 对象。

 类似资料: