Why is my Protobuf message (in Python) ignoring zero values?

ぃ、小莉子 提交于 2021-02-04 17:16:40

问题


I've been working on implementing protobufs for IPC for a project. For some reason, values that are set to 0 are not being set/serialized. For context, the .proto file contains the following message:

syntax = "proto3";

enum SetGet {
    SET = 0;
    GET = 1;
}

message State {
    SetGet setget = 1;
    double x = 2;
    double y = 3;
    double depth = 4;
    double yaw = 5;
    double pitch = 6;
    double roll = 7; 
}

I compile the file to a Python _pb2 file with protoc, and then I try running the following test script:

import filename_pb2 as pb

state = pb.State()
state.x = 0
state.y = 0
state.depth = 0
state.yaw = 0
state.pitch = 0
state.roll = 0
state.setget = pb.SET

print("State: {}".format(state))

state2 = pb.State()
state2.ParseFromString(state.SerializeToString())

print("State2: {}".format(state2))

When I run it, the following output is printed:

State: 
State2: 

It seems that nothing is being set, or that the zero values are somehow being ignored. However, when I change the values (x, y, depth, etc.) to something nonzero, say 0.1, I get the following, expected result:

State: x: 0.1
y: 0.1
depth: 0.1
yaw: 0.1
pitch: 0.1
roll: 0.1

State2: x: 0.1
y: 0.1
depth: 0.1
yaw: 0.1
pitch: 0.1
roll: 0.1

Even though the numbers are printed out, for some reason the enum still isn't. Why does this happen with protobufs? Is the double type 0 by default, so the protobuf serializer saves on space by ignoring them? Why, then, are they not being restored when State2 is parsed in? Is there some line in the documentation that I missed? Thanks in advance!

-- Tim


回答1:


Yes, 0 is the default. This case is mentioned explicitly in the documentation:

Note that for scalar message fields, once a message is parsed there's no way of telling whether a field was explicitly set to the default value (for example whether a boolean was set to false) or just not set at all: you should bear this in mind when defining your message types. For example, don't have a boolean that switches on some behaviour when set to false if you don't want that behaviour to also happen by default. Also note that if a scalar message field is set to its default, the value will not be serialized on the wire.




回答2:


Zero is the default for numerics in protobuf, and empty strings are defaults for strings. For efficiency, default values are not transmitted across the wire.

If you really want to be able to tell if it was set explicitly, don't use the default zero for a real operation:

enum SetGet {
    NONE = 0;
    SET = 1;
    GET = 2;
}

Just keep in mind this will result in extra traffic over the wire and, since you're only really worried out what's being printed, you can alternatively just understand that zeros are defaults, or write your own print routines that output everything.



来源:https://stackoverflow.com/questions/47373976/why-is-my-protobuf-message-in-python-ignoring-zero-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!