在python文件中使用google.protobuf.Any

Ken*_*tov 9 python protocol-buffers any

我有这样的.proto档案

syntax = "proto3";
import "google/protobuf/any.proto";

message Request {
  google.protobuf.Any request_parameters = 1;
}
Run Code Online (Sandbox Code Playgroud)

如何创建Request对象并填充其字段?我试过这个:

import ma_pb2
from google.protobuf.any_pb2 import Any

parameters = {"a": 1, "b": 2}
Request = ma_pb2.Request()
some_any = Any()
some_any.CopyFrom(parameters)
Request.request_parameters = some_any
Run Code Online (Sandbox Code Playgroud)

但是我有一个错误:

TypeError: Parameter to CopyFrom() must be instance of same class: expected google.protobuf.Any got dict.
Run Code Online (Sandbox Code Playgroud)

UPDATE

在提示@Kevin之后,我向.proto文件中添加了新消息:

message Small {
  string a = 1;
}
Run Code Online (Sandbox Code Playgroud)

现在代码如下所示:

Request = ma_pb2.Request()
small = ma_pb2.Small()
small.a = "1"

some_any = Any()
some_any.Pack(small)

Request.request_parameters = small
Run Code Online (Sandbox Code Playgroud)

但在最后一次作业时我有一个错误:

Request.request_parameters = small
AttributeError: Assignment not allowed to field "request_parameters" in protocol message object.
Run Code Online (Sandbox Code Playgroud)

我做错了什么?

Kev*_*vin 10

Any不是用于存储任意键和值的魔术盒.目的Any表示"任何"消息类型,如果您可能不知道在运行时要使用哪条消息.但是在运行时,您仍需要记住一些特定的消息.然后,您可以使用.Pack().Unpack()方法,该消息转换为Any,并在这一点上,你会做类似的东西Request.request_parameters.CopyFrom(some_any).

所以,如果你想存储这个特定的字典:

{"a": 1, "b": 2}
Run Code Online (Sandbox Code Playgroud)

...你需要一个.proto文件来描述一些名为a和的整数字段的消息类型b.就个人而言,我认为这有点过分; 只是扔你ab领域直接进入Request消息,除非你有一个很好的理由为他们分离出.如果你"忘记"其中一个键,你可以随时添加它,所以不要过于担心完整性.


如果你真的想要一个"用于存储任意键和值的魔术盒",而不是我上面描述的,你可以使用Map而不是Any.这样做的好处是,在密钥集可能包含任意字符串(例如,HTTP标头)的情况下,不要求您预先声明所有密钥.它的缺点是难以进行lint或类型检查(特别是在静态类型语言中),因为你可以比一个属性更容易拼错一个字符串.如链接资源中所示,映射基本上是重复字段的语法糖,如下所示(也就是说,线上表示与您执行此操作时所获得的完全相同,因此它向后兼容客户端不支持地图):

message MapFieldEntry {
  key_type key = 1;
  value_type value = 2;
}

repeated MapFieldEntry map_field = N;
Run Code Online (Sandbox Code Playgroud)

  • 哦,对了,这是一个消息字段,您需要[执行此操作](https://developers.google.com/protocol-buffers/docs/reference/python- generated#embedded_message)。 (2认同)