在 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.
更新
按照@Kevin 的提示,我向 .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
的目的是 denote "any" message type, in cases where you might not know which message you want to use until runtime. But at runtime, you still need to have some specific message in mind. You can then use the .Pack()
and .Unpack()
methods to convert that message into an Any
, and at that point you would do something like Request.request_parameters.CopyFrom(some_any)
.
所以,如果你想存储这个特定的字典:
{"a": 1, "b": 2}
...您需要一个 .proto
文件,该文件描述了一些具有名为 a
和 b
的整数字段的消息类型。就个人而言,我认为这是矫枉过正;只需将 a
和 b
字段直接放入 Request
消息中,除非您有充分的理由将它们分开。如果您 "forget" 这些键之一,you can always add it later,那么不要太担心完整性。
如果你真的想要 "magic box for storing arbitrary keys and values" 而不是我上面描述的,你可以使用 Map 而不是 Any
。这样做的好处是不需要您预先声明所有密钥,以防密钥集可能包含任意字符串(例如,HTTP headers)。它的缺点是更难进行 lint 或 type-check(尤其是在 statically-typed 语言中),因为与属性相比,字符串更容易拼错。如链接资源所示,地图基本上是重复字段的语法糖,如下所示(也就是说, on-wire 表示与您从中获得的完全相同,因此它向后兼容客户端不支持地图):
message MapFieldEntry {
key_type key = 1;
value_type value = 2;
}
repeated MapFieldEntry map_field = N;
我有这样的.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.
更新
按照@Kevin 的提示,我向 .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
的目的是 denote "any" message type, in cases where you might not know which message you want to use until runtime. But at runtime, you still need to have some specific message in mind. You can then use the .Pack()
and .Unpack()
methods to convert that message into an Any
, and at that point you would do something like Request.request_parameters.CopyFrom(some_any)
.
所以,如果你想存储这个特定的字典:
{"a": 1, "b": 2}
...您需要一个 .proto
文件,该文件描述了一些具有名为 a
和 b
的整数字段的消息类型。就个人而言,我认为这是矫枉过正;只需将 a
和 b
字段直接放入 Request
消息中,除非您有充分的理由将它们分开。如果您 "forget" 这些键之一,you can always add it later,那么不要太担心完整性。
如果你真的想要 "magic box for storing arbitrary keys and values" 而不是我上面描述的,你可以使用 Map 而不是 Any
。这样做的好处是不需要您预先声明所有密钥,以防密钥集可能包含任意字符串(例如,HTTP headers)。它的缺点是更难进行 lint 或 type-check(尤其是在 statically-typed 语言中),因为与属性相比,字符串更容易拼错。如链接资源所示,地图基本上是重复字段的语法糖,如下所示(也就是说, on-wire 表示与您从中获得的完全相同,因此它向后兼容客户端不支持地图):
message MapFieldEntry {
key_type key = 1;
value_type value = 2;
}
repeated MapFieldEntry map_field = N;