You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生成的Protobuf Python类异常,无法进行序列化与解析操作

问题描述

我正在尝试Protobuf官方Python教程的首个示例,这是我的.proto文件:

syntax = "proto2";

package tutorial;

message Person {
  optional string name = 1;
  optional int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    PHONE_TYPE_UNSPECIFIED = 0;
    PHONE_TYPE_MOBILE = 1;
    PHONE_TYPE_HOME = 2;
    PHONE_TYPE_WORK = 3;
  }

  message PhoneNumber {
    optional string number = 1;
    optional PhoneType type = 2 [default = PHONE_TYPE_HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

我在终端进入该proto文件所在目录,执行了编译命令:

protoc --python_out=../Generated addressbook.proto

生成的addressbook_pb2.py内容如下:

# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: addressbook.proto
# Protobuf Python Version: 4.25.2
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()



DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x61\x64\x64ressbook.proto\x12\x08tutorial\"\xa3\x02\n\x06Person\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\x05\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12,\n\x06phones\x18\x04 \x03(\x0b\x32\x1c.tutorial.Person.PhoneNumber\x1aX\n\x0bPhoneNumber\x12\x0e\n\x06number\x18\x01 \x01(\t\x12\x39\n\x04type\x18\x02 \x01(\x0e\x32\x1a.tutorial.Person.PhoneType:\x0fPHONE_TYPE_HOME\"h\n\tPhoneType\x12\x1a\n\x16PHONE_TYPE_UNSPECIFIED\x10\x00\x12\x15\n\x11PHONE_TYPE_MOBILE\x10\x01\x12\x13\n\x0fPHONE_TYPE_HOME\x10\x02\x12\x13\n\x0fPHONE_TYPE_WORK\x10\x03\"/\n\x0b\x41\x64\x64ressBook\x12 \n\x06people\x18\x01 \x03(\x0b\x32\x10.tutorial.Person')

_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'addressbook_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
  DESCRIPTOR._options = None
  _globals['_PERSON']._serialized_start=32
  _globals['_PERSON']._serialized_end=323
  _globals['_PERSON_PHONENUMBER']._serialized_start=129
  _globals['_PERSON_PHONENUMBER']._serialized_end=217
  _globals['_PERSON_PHONETYPE']._serialized_start=219
  _globals['_PERSON_PHONETYPE']._serialized_end=323
  _globals['_ADDRESSBOOK']._serialized_start=325
  _globals['_ADDRESSBOOK']._serialized_end=372
# @@protoc_insertion_point(module_scope)

但我在生成的文件里找不到可用的类,不清楚怎么用这个文件做数据序列化和解析。


解决方法

生成的Python文件中,类是通过_builder动态构建的,所以源码里看不到显式的类定义,但导入后就能直接使用。以下是具体的使用示例:

1. 导入生成的模块

确保../Generated目录在Python的sys.path中,然后导入:

import addressbook_pb2

2. 创建实例并赋值

# 创建AddressBook实例
address_book = addressbook_pb2.AddressBook()

# 创建Person实例并添加到AddressBook
person = address_book.people.add()
person.name = "Alice"
person.id = 1234
person.email = "alice@example.com"

# 添加电话号码
phone = person.phones.add()
phone.number = "123-456-7890"
phone.type = addressbook_pb2.Person.PHONE_TYPE_MOBILE

phone2 = person.phones.add()
phone2.number = "987-654-3210"
# 不指定type的话会使用默认值PHONE_TYPE_HOME

3. 序列化数据

把对象序列化成二进制字节流:

serialized_data = address_book.SerializeToString()
# 可以把serialized_data写入文件或通过网络传输

4. 解析二进制数据

从字节流还原成对象:

# 假设serialized_data是接收到的二进制数据
new_address_book = addressbook_pb2.AddressBook()
new_address_book.ParseFromString(serialized_data)

# 访问解析后的数据
for person in new_address_book.people:
    print(f"Name: {person.name}")
    print(f"ID: {person.id}")
    print(f"Email: {person.email}")
    for phone in person.phones:
        type_name = addressbook_pb2.Person.PhoneType.Name(phone.type)
        print(f"Phone ({type_name}): {phone.number}")

关键说明

  • 生成的类名和你.proto文件中定义的message/enum一一对应,比如Person、AddressBook、Person.PhoneNumber、Person.PhoneType。
  • 对于repeated字段,使用add()方法添加新元素,就像示例中address_book.people.add()和person.phones.add()。
  • 序列化用SerializeToString(),解析用ParseFromString(),这是Protobuf Python API的标准方法。

内容的提问来源于stack exchange,提问作者HENSEL WILSON GOVEAS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:33:26