如果子消息没有字段,如何在protobuf消息上分配oneof字段?

时间:2018-06-11 08:23:53

标签: python grpc bigtable

我想创建一个BigTable DeleteFromRow突变。 MutationDeleteFromRow的原型如下所示:

oneof mutation {
    // Set a cell's value.
    SetCell set_cell = 1;

    // Deletes cells from a column.
    DeleteFromColumn delete_from_column = 2;

    // Deletes cells from a column family.
    DeleteFromFamily delete_from_family = 3;

    // Deletes cells from the entire row.
    DeleteFromRow delete_from_row = 4;
  }
}

message DeleteFromRow {

}

在Python中,您无法直接实例化DeleteFromRow对象并将delete_from_row的{​​{1}}字段设置为该对象。

所以不起作用

Mutation

由其他SO用户提出(请参阅this question),结果为

request = bigtable_pb2.MutateRowRequest(table_name='tablename', row_key=row_key)
mutation = request.mutations.add()
mutation.delete_from_row = data_pb2.Mutation.DeleteFromRow()

根据protobuf docs,您应该通过设置其中一个子字段来设置oneof字段。因此应该以这种方式创建AttributeError: Assignment not allowed to composite field "delete_from_row" in protocol message object. 突变:

DeleteFromFamily

但是,如何为没有字段的mutation.delete_from_family.family_name = 'some_family' 消息执行此操作?

2 个答案:

答案 0 :(得分:1)

您可以启动DeleteFromRow对象并使用关键字参数delete_from_row创建变异:

dfr = data_pb2.Mutation.DeleteFromRow()
mutation = data_pb2.Mutation(delete_from_row=dfr)

虽然你不能addappend这个突变到请求的重复突变字段(虽然在我看来这就是文档所说的here),但是你可以 extend

request = bigtable_pb2.MutateRowRequest(table_name='tablename', row_key=row_key)
request.mutations.extend([mutation])

答案 1 :(得分:1)

您可以使用Message.SetInParent

将此标记为存在于父项中。

这通常在您分配子消息的字段时自动发生,但是有时您希望在保留子消息为空的同时使其显示。如果您发现自己正在使用它,则可能需要重新考虑您的设计。

示例:

message Msg {
  oneof kind {
    int64 int_field = 1;
    EmptyMsg msg_field = 1;
  }
}

message EmptyMsg {}
msg = Msg()
print(msg.WhichOneof('kind'))  # None

msg.msg_field  # No-op (return EmptyMsg but don't set oneof field)
print(msg.WhichOneof('kind'))  # None

msg.msg_field.SetInParent()
print(v.WhichOneof('kind'))  # msg_field