首页 > 解决方案 > protobuf 包是如何使用的?

问题描述

我不明白谷歌的 Python protobuf 文档中关于包的最后一句的第一部分:

.proto文件以包声明开头,这有助于防止不同项目之间的命名冲突。在 Python 中,包通常由目录结构决定,因此您在.proto文件中定义的包对生成的代码没有影响。但是,您仍然应该声明一个,以避免在 Protocol Buffers 名称空间以及非 Python 语言中发生名称冲突。

实际上,“您在.proto文件中定义的包对生成的代码没有影响”在 Python 中(并且可能因此在使用命名空间的语言中)实际上是错误的,因为生成的..._pb2.py文件包含具有包字段的描述符。

DESCRIPTOR = _descriptor.FileDescriptor(
  name='example.proto',
  package='example',
  syntax='proto3',
   ...
)

我已经检查过了,生成代码后你不能import example进入常规的 python 文件。即package example;在您的.proto文件中声明然后protoc编译它不会自动使您的包可用于在您的环境中的python 文件中导入(您仍然必须使用import ..._pb2来访问类)。

有没有人能够解释如何.proto在 Python 中使用文件中声明的包并说 C# 作为明确使用命名空间的语言的示例?

标签: c#python-3.xpackageprotocol-buffers

解决方案


引用文档本身:

在 Python 中,package 指令被忽略,因为 Python 模块是根据它们在文件系统中的位置来组织的。

那么包声明到底有什么用呢?我相信两件事:

  1. 避免消息对象中出现命名冲突的可能性。如果假设您有一条消息在同一个应用程序下声明不同,那么您可以考虑在 proto 文件的开头提供包说明符,然后在定义其他消息类型的字段时使用指定的包。例如,如果Foo定义在package barpackage baz两者之下;然后在需要bar.Foobaz.Foo地方使用。

  2. 为了便携。包指令在 Python 和 Golang 中都被忽略。但是像 C++ 和 C# 这样显式创建命名空间的语言确实会考虑指定的包。所以Foo在上面的例子中,一个名为的消息类型将在和Foo的命名空间中声明。您使用 Python 应用程序创建的 proto 文件可以以几乎相同的方式为您的 C# 应用程序编译。需要注意的是,Protobuf 是用于序列化和反序列化数据的语言无关机制。barbaz

话虽如此,我个人并没有在我的 Python 应用程序的 protobuf 消息中发现包说明符的使用。

参考:https ://developers.google.com/protocol-buffers/docs/proto


推荐阅读