无需生成中间文件从proto文件加载FileDescriptorSet的实现方案问询
无中间文件动态加载Proto描述符的实现方案
有的,两种常用方案都可以实现无中间文件的内存级描述符加载,直接得到google.protobuf.descriptor_pb2.FileDescriptorSet对象,具体实现如下:
方案1:调用本地protoc捕获标准输出(通用性最强)
protoc原生支持将描述符集输出到标准输出,不需要落地到磁盘文件,你可以直接通过Python子进程捕获输出流,直接解析为目标对象。
代码示例
import subprocess from google.protobuf.descriptor_pb2 import FileDescriptorSet def load_descriptor_set(proto_paths: list[str], proto_files: list[str], include_imports: bool = True) -> FileDescriptorSet: # 构造protoc执行命令 cmd = ["protoc"] # 添加proto文件搜索路径 for path in proto_paths: cmd.append(f"--proto_path={path}") # 指定描述符集输出到标准输出 cmd.append("--descriptor_set_out=-") if include_imports: # 若需要把依赖的导入proto也纳入描述符集,添加该参数 cmd.append("--include_imports") # 加入要处理的proto文件列表 cmd.extend(proto_files) # 执行命令捕获二进制输出 exec_result = subprocess.run(cmd, capture_output=True, check=True) # 直接解析输出为FileDescriptorSet对象 fd_set = FileDescriptorSet() fd_set.ParseFromString(exec_result.stdout) return fd_set
使用示例
# 处理当前目录下的test.proto文件 fd_set = load_descriptor_set(proto_paths=["."], proto_files=["test.proto"]) # 可直接操作fd_set对象,全程无中间文件生成
方案2:纯Python实现(无需本地安装protoc)
如果不想依赖本地安装的protoc二进制文件,可以用grpcio-tools包中封装的纯Python版protoc实现相同能力,只需要提前安装依赖:pip install grpcio-tools
代码示例
from google.protobuf.descriptor_pb2 import FileDescriptorSet from grpc_tools import protoc def load_descriptor_set_pure_py(proto_paths: list[str], proto_files: list[str], include_imports: bool = True) -> FileDescriptorSet: args = [] for path in proto_paths: args.append(f"--proto_path={path}") # 指定输出到标准输出,Windows环境可替换为 --descriptor_set_out=CON args.append("--descriptor_set_out=/dev/stdout") if include_imports: args.append("--include_imports") args.extend(proto_files) # 调用protoc捕获标准输出 stdout_bytes = protoc.main(args, capture_stdout=True) fd_set = FileDescriptorSet() fd_set.ParseFromString(stdout_bytes) return fd_set
注意事项
- 以上两种方案都不会生成任何本地中间文件,描述符全程在内存中处理
- 若后续需要把
FileDescriptorSet转换成可直接序列化/反序列化的消息类,可以配合google.protobuf.descriptor_pool和google.protobuf.message_factory完成动态消息类构建 - 如果仅处理单个proto文件且无复杂依赖,第二种纯Python方案更便捷,无需提前配置protoc本地环境
内容的提问来源于stack exchange,提问作者aarnaut
相关产品推荐
相关产品推荐

