繁体   English   中英

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

[英]Using google.protobuf.Any in python file

我有这样的.proto文件

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

message Request {
  google.protobuf.Any request_parameters = 1;
}

如何创建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

但是我有一个错误:

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

UPDATE

在提示@Kevin后,我向.proto文件添加了.proto

message Small {
  string a = 1;
}

现在代码如下所示:

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

some_any = Any()
some_any.Pack(small)

Request.request_parameters = small

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

Request.request_parameters = small
AttributeError: Assignment not allowed to field "request_parameters" in protocol message object.

我做错了什么?

Any不是用于存储任意键和值的魔术盒。 Any的目的是表示“任何”消息类型 ,以防您在运行时可能不知道要使用哪条消息。 但是在运行时,您仍需要记住一些特定的消息。 然后,您可以使用.Pack().Unpack()方法将该消息转换为Any此时您将执行类似Request.request_parameters.CopyFrom(some_any)

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

{"a": 1, "b": 2}

...你需要一个.proto文件来描述一些包含名为ab整数字段的消息类型。 就个人而言,我认为这有点过分; 只需将ab字段直接放入Request消息中,除非你有充分的理由将它们分开。 如果你“忘记”其中一个键, 你可以随时添加它 ,所以不要过于担心完整性。


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

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

repeated MapFieldEntry map_field = N;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM