news 2026/9/10 21:39:01

FlatBuffers Python 使用指南:库结构、读写与 NumPy 向量加速

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FlatBuffers Python 使用指南:库结构、读写与 NumPy 向量加速

FlatBuffers Python 使用指南:库结构、读写与 NumPy 向量加速

【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers

本篇指南基于 FlatBuffers 官方文档中 Python 语言章节,系统讲解如何在 Python 中读写 FlatBuffers 二进制数据:包括 Python 运行库在仓库中的位置、flatc --python代码生成与项目集成方式、GetRootAsMonster读取流程、AsNumpy()向量零拷贝加速,以及文本解析的能力边界。读完本文,你将能够独立完成"编写 schema → 生成 Python 代码 → 序列化/反序列化 → 用 NumPy 批量读取标量向量"的完整链路。

开始之前:需要掌握的前置知识

本文是 Tutorial 的 Python 语言专项补充,聚焦 Python 使用上的细节与差异。建议在阅读本文前先完成以下准备工作:

  • 通读 Tutorial:其中包含全部支持语言(含 Python)的完整使用指南,覆盖 schema 编写、flatc编译、应用集成、序列化与反序列化全流程;
  • 阅读 Building 文档并构建出flatc编译器;
  • 熟悉 Using the schema compiler 与 Writing a schema,掌握flatc的命令行用法与.fbsschema 语法。
# 在仓库根目录下用 CMake 构建 flatc(Unix 环境) cmake -G "Unix Makefiles" make flatc

构建完成后,flatc可执行文件位于仓库根目录(tests/PythonTest.sh正是以../flatc方式引用它)。

FlatBuffers Python 库代码位置

Python 运行时库的源码位于仓库的python/flatbuffers目录,由以下核心模块组成:

模块文件职责
python/flatbuffers/builder.pyBuilder类,序列化核心,管理字节缓冲与 vtable
python/flatbuffers/table.pyTable类,只读访问器基类,提供向量/字符串/联合的读取
python/flatbuffers/encode.py标量编解码与GetVectorAsNumpy实现
python/flatbuffers/number_types.py各标量类型的 packer 与 NumPy dtype 映射
python/flatbuffers/packer.py基于struct的小端二进制打包
python/flatbuffers/compat.pyPython 2/3 兼容层与 NumPy 可选依赖探测
python/flatbuffers/flexbuffers.pyFlexBuffers 变长格式支持
python/flatbuffers/util.py工具函数(如GetBufferIdentifier

该目录还提供标准的打包配置:python/setup.py(当前版本号25.12.19)与 python/setup.cfg,可通过pip install flatbuffers安装,或直接将python目录加入PYTHONPATH使用仓库内源码。

测试 Python 库

Python 库的测试代码位于 tests/py_test.py,覆盖了对象 API、向量、联合、gRPC、NumPy 向量等大量场景。运行测试使用 tests/PythonTest.sh 脚本:

# 需已安装 Python;脚本会自动探测可用的解释器 cd tests ./PythonTest.sh

该脚本会依次完成以下工作(详见 tests/PythonTest.sh):

  1. 用仓库内flatc针对monster_test.fbsmonster_extra.fbsarrays_test.fbsnested_union_test.fbsservice_test.fbs等 schema 生成 Python 代码,生成命令带有--gen-object-api--python-typing--gen-compare--gen-onefile--grpc--grpc-python-typed-handlers--no-python-gen-numpy--python-decode-obj-api-strings等选项;
  2. 依次用python2.6python2.7python3pypy运行 tests/py_test.py(若环境中存在),并对python3额外运行 tests/py_flexbuffers_test.py;
  3. 若安装了coveragepip install coverage),还会以默认 Python 生成覆盖率报告;
  4. 若系统没有任何 Python 解释器,则输出 "No Python interpreters found" 并退出码 1。

运行方式示例:python3 py_test.py 100 100 100 100 false(后四个参数是 vtable 去重、读/写基准测试的次数与开关)。

在 Python 中使用 FlatBuffers

Python 同时支持 FlatBuffers 的读取写入。整体流程是:先用flatc--python选项从 schema 生成 Python 类,然后在业务代码中同时导入 FlatBuffers 运行时库与生成的代码。

第一步:用 flatc 生成 Python 代码

flatc --python monster.fbs

生成的文件会按 schema 中的namespace组织成对应的 Python 包(例如MyGame/Example目录下的Monster.pyVec3.py等)。以本仓库 samples/monster.fbs 为例,其namespace MyGame.Sample;会生成MyGame/Sample/包。也可以像测试脚本那样追加--gen-object-api(生成可变的 Object API 与Pack/UnPack方法)、--python-typing(生成.pyi类型标注文件)等选项。

第二步:读取一个 FlatBuffer 二进制文件

import MyGame.Example as example # flatc --python 生成的代码 import flatbuffers # 运行时库 # 将二进制文件读入 bytearray buf = open('monster.dat', 'rb').read() buf = bytearray(buf) # 以根对象方式解析 monster = example.GetRootAsMonster(buf, 0)

随后即可像普通访问器一样读取字段:

hp = monster.Hp() pos = monster.Pos()

这里的GetRootAsMonster(buf, 0)flatc生成代码提供的入口函数:bufbytearray形式的二进制数据,0是根对象在缓冲中的偏移。读取器底层由 python/flatbuffers/table.py 中的Table类支撑——它保存BytesPos两个状态,通过Offset()查询 vtable、Get()解码标量、String()/Vector()解析引用类型,并利用GetSlot()在字段缺失时返回 schema 中声明的默认值,因此读取过程不产生反序列化副本、无需解析整棵树,这正是 FlatBuffers 零拷贝读取特性的体现。

写入(序列化)示例

如果需要写入,则使用 python/flatbuffers/builder.py 中的Builder

import flatbuffers import MyGame.Sample.Monster import MyGame.Sample.Vec3 import MyGame.Sample.Color import MyGame.Sample.Equipment # 构造 Builder,默认初始缓冲 1024 字节,需要时会自动扩容 builder = flatbuffers.Builder(1024) # 引用类型(string、vector、table)需先序列化,自叶子向根构建 name = builder.CreateString("Orc") inv = builder.CreateStringVector([0, 1, 2, 3]) # 或用 CreateNumpyVector MyGame.Sample.Monster.Start(builder) MyGame.Sample.Monster.AddPos(builder, MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)) MyGame.Sample.Monster.AddHp(builder, 300) MyGame.Sample.Monster.AddName(builder, name) MyGame.Sample.Monster.AddInventory(builder, inv) MyGame.Sample.Monster.AddColor(builder, MyGame.Sample.Color.Color().Red) orc = MyGame.Sample.Monster.End(builder) builder.Finish(orc) # 标记根对象 buf = builder.Output() # 必须在 Finish() 之后调用,返回 bytearray

从源码实现看,Builder的几个关键行为值得注意(见 python/flatbuffers/builder.py):

  • 向后构建:缓冲从尾部向前写入,head指向当前写入位置,读取时无需前向解析;
  • 初始大小与上限Builder(initialSize=1024),缓冲可自动增长,但受MAX_BUFFER_SIZE = 2**31(2 GiB)硬上限约束,超过会抛出BuilderSizeError
  • vtable 去重WriteVtable()会将新 vtable 与已记录的self.vtables比较,内容相同的对象复用已有 vtable,从而显著压缩重复结构的内存占用;
  • Output()前必须Finish():否则抛出BuilderNotFinishedErrorOutput()返回的是Bytes[head:]切片,即实际已写入的数据;
  • 序列化过程的状态机还会抛出IsNotNestedErrorIsNestedErrorStructIsNotInlineErrorEndVectorLengthMismatched等异常,用于在嵌套/顺序错误时给出明确提示。

对 NumPy 数组的支持

Python 库对标量向量提供 NumPy 数组访问支持。相比逐元素迭代,这可以带来数量级的性能提升,尤其在解包大型嵌套 FlatBuffers 时优势明显。生成的代码会为每个标量向量提供一个<vector name>AsNumpy()方法。以 Monster 示例的inventory向量为例:

inventory = monster.InventoryAsNumpy() # inventory 是一个 numpy 数组,类型为 np.dtype('uint8')

而不是:

inventory = [] for i in range(monster.InventoryLength()): inventory.append(int(monster.Inventory(i)))

从实现看,AsNumpy()的底层链路是:生成的访问器调用Table.GetVectorAsNumpy()(见 python/flatbuffers/table.py),先定位向量起始位置与长度,再按字段类型映射到 NumPy dtype(映射表在 python/flatbuffers/number_types.py 的to_numpy_type),最终在 python/flatbuffers/encode.py 中通过np.frombuffer(buf, dtype=numpy_type, count=count, offset=offset)构造数组。也就是说,返回的 NumPy 数组是原缓冲区的零拷贝视图(view)——修改该数组会直接改动底层Bytes,同时避免了逐元素 Python 循环的开销。

NumPy 不是必需依赖

NumPy 是可选依赖。运行库在 python/flatbuffers/compat.py 的import_numpy()中通过探测模块是否存在来决定是否导入:存在则正常加载,不存在则置为None

  • 若系统未安装NumPy,调用任何*AsNumpy()方法都会抛出NumpyRequiredForThisFeature异常(该异常继承自RuntimeError,定义于 python/flatbuffers/compat.py);
  • 因此,只有当你确实需要 NumPy 向量访问时,才需要额外安装pip install numpy
  • 官方测试 tests/py_test.py 对此做了双向验证:当 NumPy 存在时,断言InventoryAsNumpy().dtype == np.dtype('<u1')sum() == 10;当 NumPy 不存在时,则断言访问AsNumpy()会抛出NumpyRequiredForThisFeature

该特性同时覆盖多种标量类型与固定长度数组:测试中还包含TestarrayofboolsAsNumpyVectorOfLongsAsNumpyVectorOfDoublesAsNumpyVectorOfEnumsAsNumpy以及test_create_numpy_vector_*系列用例(对应CreateNumpyVector写入 API),说明布尔、长整型、浮点、枚举向量乃至arrays_test的定长数组都可享受同样的零拷贝批量访问能力。

文本解析(JSON/Schema)说明

目前 Python 库不支持直接从 Python 解析文本格式(包括.fbsschema 与 JSON 数据)。如果需要文本解析能力,官方文档给出的路径是:

  • 通过 SWIG 或 ctypes 包装并调用 C++ 解析器;
  • 或者直接查阅 C++ 文档(docs/source/languages/cpp.md)了解文本解析的完整实现。

这也意味着 Python 侧的常规使用方式是:schema 文本交由flatc编译为二进制flatc文件或直接生成代码,JSON 与二进制之间的转换可借助flatc -t --json等命令完成,而运行时只处理二进制格式。

小结

  • 库位置:运行时库在 python/flatbuffers,可通过pip install flatbuffers安装或以PYTHONPATH引用仓库源码;
  • 读写流程flatc --python monster.fbs生成代码 → 导入flatbuffers与生成包 → 读取用GetRootAsMonster(buf, 0),写入用Builder+Start/Add/End+Finish()+Output()
  • 性能关键点:标量向量用<name>AsNumpy()获得零拷贝 NumPy 视图,避免逐元素迭代;NumPy 为可选依赖,缺失时访问会抛NumpyRequiredForThisFeature
  • 能力边界:文本(schema/JSON)解析需借助 C++ 解析器(SWIG/ctypes),Python 库本身不提供。

如需完整的逐语言对照示例与 schema 类型系统讲解,请继续阅读 Tutorial、Writing a schema 与 Using the schema compiler。

【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 21:38:26

CANN/ge TimeBatch时间批次功能

&#xfeff;# TimeBatch 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、T…

作者头像 李华
网站建设 2026/9/10 21:35:14

CANN/ge C++融合Pass开发指南

C Fusion Pass Development Guide 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 Py…

作者头像 李华
网站建设 2026/9/10 21:34:57

开源能源管理系统MyEMS:企业节能降本的关键技术

1. 开源能源管理系统为何成为企业刚需&#xff1f; 去年夏天&#xff0c;我亲眼见证了一家电子制造厂的能源账单危机。当电费单上的数字突破七位数时&#xff0c;厂长拍着桌子说&#xff1a;"我们必须找到控制能耗的方法&#xff01;"这正是MyEMS这类开源能源管理系统…

作者头像 李华