生成的代码参考
生成的代码参考
gRPC Python 依赖于 Protocol Buffers 编译器(protoc
)来生成代码。它使用一个插件来补充纯 protoc
生成的代码,添加 gRPC 特定的代码。对于包含 gRPC 服务的 .proto
服务描述,纯 protoc
生成的代码会合成到一个 _pb2.py
文件中,而 gRPC 特定的代码则位于一个 _pb2_grpc.py
文件中。后者 Python 模块会导入前者。本页面重点介绍生成的代码中 gRPC 特定的子集。
示例
考虑以下 FortuneTeller
proto 服务
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
}
}
编译该服务时,gRPC protoc
插件会生成类似于以下 _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 特定的代码元素,例如与 Protocol Buffers 消息相对应的类以及反射使用的描述符。
对于 .proto
文件中的每个服务 Foo
,会生成三个主要元素
- Stub:
FooStub
供客户端用于连接 gRPC 服务。 - Servicer:
FooServicer
供服务端用于实现 gRPC 服务。 - 注册函数:
add_FooServicer_to_server
函数用于向grpc.Server
对象注册 Servicer。
Stub
生成的 Stub
类由 gRPC 客户端使用。它有一个构造函数,接受一个 grpc.Channel
对象并初始化 Stub。对于服务中的每个方法,初始化程序都会向 Stub 对象添加一个同名属性。根据 RPC 类型(一元或流式),该属性的值将是类型为 UnaryUnaryMultiCallable, UnaryStreamMultiCallable, StreamUnaryMultiCallable 或 StreamStreamMultiCallable 的可调用对象。
Servicer
对于每个服务,都会生成一个 Servicer
类,作为服务实现的超类。对于服务中的每个方法,都会在 Servicer
类中生成一个相应的函数。使用服务实现覆盖此函数。与 .proto
文件中代码元素关联的注释会作为文档字符串出现在生成的 Python 代码中。
注册函数
对于每个服务,都会生成一个函数,用于在 grpc.Server
对象上注册实现该服务的 Servicer
对象,以便服务器可以将查询路由到相应的 Servicer。此函数接受一个实现 Servicer
的对象(通常是上面描述的生成的 Servicer
代码元素的子类实例)和一个 grpc.Server 对象。