在一个包含必填字段和默认值的ProtoBuf消息上使用SerializeToString()方法时,总是会抛出EncodeError异常,指出消息缺少这些必填字段。但是如果我检查这些字段的值,所有默认值都已经设置了。例如:
// mymessage.proto
message MyMessage {
required int32 val = 1 [default=18];
}
然后在Python中:
from mymessage_pb2.py import MyMessage
m = MyMessage()
print m.val # Shows m.val == 18
print m.SerializeToString() # EncodeError
另一方面,如果我这样做:
m.val = m.val
print m.SerializeToString() # No Error
很明显,尽管在初始化时具有默认值,但需要触及每个字段。对我来说,拥有默认值的主要优点之一是只需要更新非默认字段(或需要更改的字段),因此将其设置为自身方法是一个很抱歉的解决方案。
将字段标记为“optional”不是一个解决方案,因为这些字段根据我们的规格要求是必需的。
更新:我的解决方法包括 MergeFrom 和 CopyFrom,但都没有成功。所以我写了这个:
def ActuallyInit(obj):
err = []
obj.IsInitialized(err)
for field in err:
attr = obj.__getattribute__(field)
try:
obj.__setattr__(field, attr)
except:
ActuallyInit(attr)
然后创建protobuf对象并将其传递给ActuallyInit
,该函数会递归地将每个字段设置为默认值。这看起来像是一种丑陋的hack,因此我将下面的问题保留为开放式。
问题:是否有一种方法可以创建ProtoBuf消息实例并“说服”它,让每个已初始化为默认值的字段实际上不是错误?