ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Apache Arrow PyArrow 架构深度解析:从 .py 到 .pxd 的四层源码结构与 PyArrow C++ 支撑层

Apache Arrow PyArrow 架构深度解析:从 .py 到 .pxd 的四层源码结构与 PyArrow C++ 支撑层 Apache Arrow PyArrow 架构深度解析从 .py 到 .pxd 的四层源码结构与 PyArrow C 支撑层【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow本文以 Apache Arrow 仓库中 Python 文档的 Getting Involved 与 PyArrow Architecture 章节为核心讲清楚 PyArrow 的参与途径与整体分层架构PyArrow 主体上是对 Arrow Clibarrow能力的封装层通过*.py、lib.pyx/*.pxi、_*.pyx、includes/*.pxd四层加上独立的 PyArrow C 层把 C 的列式能力转译为更 Pythonic 的 API。读完本文你能掌握 PyArrow 各层文件在 python/pyarrow/ 目录中的分工与调用关系知道在贡献、排错或阅读源码时应该从哪一层入手并能顺藤摸瓜定位到 Arrow 格式规范与底层实现。如何参与 Apache ArrowArrow 文档指出当前 Arrow 的主要受众是数据系统的开发者大多数人会通过间接使用它来处理内部数据、并与其它支持 Arrow 的系统互操作的系统来接触 Arrow。即使你并不打算向 Arrow 本身或其集成项目贡献代码官方同样欢迎你参与社区加入邮件列表向dev-subscribearrow.apache.org发送邮件即可订阅你可以在列表中分享自己对项目的想法和用例也可以浏览历史邮件存档。关注 GitHub 上的动态跟踪 Apache Arrow 在 GitHub 上的 issue 与讨论是了解项目进展、寻找可贡献问题的最直接方式。学习格式规范Arrow 的跨语言列式内存格式由一套格式规范定义仓库根目录的 format/ 目录即存放这些规范文件例如 Message.fbsIPC 消息格式、Schema.fbs模式序列化与 File.fbsIPC 文件格式它们以 FlatBuffers Schema 形式描述是理解 Arrow 跨语言互操作约定的第一手资料。PyArrow 的定位C 能力的 Pythonic 封装文档对 PyArrow 的定位非常明确PyArrow 大部分是对 Arrow C 实现所提供功能的封装。库的设计目标是把 C 中可用的能力通过更 Pythonic、更不易上手出错的方式暴露出来。因此有些能力可以直接映射——Python 类与 C 类近乎一一对应更多情况下C 的类与方法只是地基PyArrow 在其上组装出更易用的实体。这一点在源码中得到直接印证。python/pyarrow/lib.pyx 开头就声明了与 C 侧的绑定关系from cython.operator cimport dereference as deref from pyarrow.includes.libarrow cimport * from pyarrow.includes.libarrow_python cimport * from pyarrow.includes.common cimport PyObject_to_object cimport pyarrow.includes.libarrow_python as libarrow_python cimport cpython as cp随后通过arrow_init_numpy()初始化 NumPy C API当前版本要求 NumPy 2.0见 lib.pyx再调用import_pyarrow()初始化 PyArrow C API。整个模块随后通过一系列include指令拼装各功能域这就是文档所说的lib.pyx 的实现大部分依赖于被包含的*.pxi文件# Assorted compatibility helpers include compat.pxi # Exception types and Status handling include error.pxi # Configuration information include config.pxi # pandas API shim include pandas-shim.pxi # Memory pools and allocation include memory.pxi # Device type and memory manager include device.pxi # DataType, Field, Schema include types.pxi # Array scalar values include scalar.pxi # Array types include array.pxi # Builders include builder.pxi # Column, Table, Record Batch include table.pxi # Tensors include tensor.pxi # DLPack include _dlpack.pxi # File IO include io.pxi # IPC / Messaging include ipc.pxi # Micro-benchmark routines include benchmark.pxi # Public API include public-api.pxi见 lib.pyx。每个*.pxi文件负责一个功能域——类型系统、标量、数组、构建器、表、张量、DLPack 互操作、文件 IO、IPC 等——pyarrow.lib对外是内部模块公共类则由其它模块如pyarrow包本身从它导入后再暴露。python/pyarrow/init.py 正是这样做的from pyarrow.lib import (BuildInfo, CppBuildInfo, RuntimeInfo, set_timezone_db_path, MonthDayNano, VersionInfo, build_info, cpp_build_info, cpp_version, cpp_version_info, runtime_info, cpu_count, set_cpu_count, enable_signal_handlers, io_thread_count, is_opentelemetry_enabled, set_io_thread_count)第一层*.py文件——面向用户的声明层文档说明pyarrow 包中的*.py文件通常是暴露给用户的实体声明处在某些情况下这些文件会直接从内部实现导入实体并原样暴露不做修改。在 python/pyarrow/ 目录中可以看到大量这类文件csv.py、feather.py、ipc.py、fs.py、json.py、orc.py、dataset.py、flight.py、compute.py等。它们承担了参数校验、默认值处理、文档字符串docstring以及高层 API 组织等纯 Python 逻辑是用户import pyarrow.csv这类语句的落点。当某个能力不需要 Python 侧额外加工时.py文件只是从 Cython 编译出的模块直接 re-export保持 API 表面简洁。第二层lib.pyx与*.pxi——核心能力的暴露层lib.pyx是把 libarrow 核心能力暴露给 Python 的主文件编译后成为pyarrow.lib模块。文档特别提醒虽然以pyarrow.lib的名称暴露在 Python 中其内容应当被视为内部实现公共类之所以能在pyarrow等模块中使用正是靠从pyarrow.lib导入。*.pxi文件按功能域组织实现。以 python/pyarrow/array.pxi数千行体量涵盖 Array/ChunkedArray 等核心类型为例其中 Python 序列转数组的入口展示了这一层的典型写法——声明PyConversionOptions来自 PyArrow C 层在nogil段中调用 C 函数释放 GIL 执行转换再把shared_ptr[CChunkedArray]包装回 Python 对象cdef _sequence_to_array(object sequence, object mask, object size, DataType type, CMemoryPool* pool, c_bool from_pandas): cdef: int64_t c_size PyConversionOptions options shared_ptr[CChunkedArray] chunked ... options.from_pandas from_pandas options.ignore_timezone os.environ.get(PYARROW_IGNORE_TIMEZONE, False) with nogil: chunked GetResultValue( ConvertPySequence(sequence, mask, options, pool) ) if chunked.get().num_chunks() 1: return pyarrow_wrap_array(chunked.get().chunk(0)) else: return pyarrow_wrap_chunked_array(chunked)见 array.pxi。ConvertPySequence与PyConversionOptions的声明来自includes/libarrow_python.pxd这正是第四层在第二层的具体消费点。第三层_*.pyx文件——胶水代码层文档指出_*.pyx文件是**胶水代码glue code**所在它们把 C 能力拼装成 Python 类与方法可以理解为*.py文件所暴露能力的内部实现。目录中这类文件一一对应各 IO 与扩展子系统_csv.pyx、_parquet.pyx、_feather.pyx、_fs.pyx、_flight.pyx、_dataset.pyx、_s3fs.pyx、_gcsfs.pyx、_hdfs.pyx、_compute.pyx、_orc.pyx、_json.pyx、_cuda.pyx、_acero.pyx 等。例如csv.py用户可见的声明层背后的 Reader/Writer 具体类由_csv.pyx编译实现。仓库自带了 Cython 用户侧使用示例可作为理解这一层的参考python/pyarrow/tests/pyarrow_cython_example.pyx 与配套的 python/pyarrow/tests/test_cython.py演示了外部项目如何声明 Arrow 类型、并在 Cython 代码中以nogil方式安全调用 Arrow API。第四层includes/*.pxd——C API 的 Cython 声明文档说明includes/*.pxd文件中是为 Cython 声明的原始 C 库 APIC 类与方法按原样声明供其它.pyx文件用来实现 Python 类、函数与辅助工具。python/pyarrow/includes/ 目录中的文件与 Arrow 的各个 C 库一一对应libarrow.pxd——核心 libarrow类型、内存池、数组、状态/状态码等文件约三千余行libarrow_python.pxd——PyArrow C 层见下一节的声明libarrow_fs.pxd、libarrow_dataset.pxd、libparquet.pxd、libparquet_encryption.pxd、libarrow_flight.pxd、libarrow_acero.pxd、libarrow_cuda.pxd、libgandiva.pxd、libarrow_substrait.pxd、libarrow_feather.pxd 等。这类声明的标准形态可以在 libarrow.pxd 中看到用cdef extern from ... namespace arrow nogil将 C 头文件中的类原样映射进 Cython 的世界并用C前缀 真实C名的别名约定避免与 Python 类型名冲突cdef extern from arrow/util/key_value_metadata.h namespace arrow nogil: cdef cppclass CKeyValueMetadata arrow::KeyValueMetadata: CKeyValueMetadata() ...nogil修饰意味着这些声明默认在释放 GIL 的上下文中使用这是 PyArrow 能把重计算下推到 C 而不阻塞解释器的关键前提。第五层PyArrow Cpython/pyarrow/src/arrow/python文档特别强调除 Arrow C 库外PyArrow 还依赖一个专门的 C 代码集——PyArrow C位于 python/pyarrow/src/arrow/python/ 目录提供低层能力与 NumPy/pandas 的相互转换以及让 C 侧可以使用 Python 对象与回调的类。从该目录的实际文件构成看这些说法完全可对应numpy_convert.cc/numpy_convert.h、numpy_to_arrow.cc、numpy_to_arrow.h、arrow_to_pandas.cc、python_to_arrow.cc——NumPy/Python 对象与 Arrow 之间的双向转换即array.pxi中调用的ConvertPySequence所在的一侧pyarrow.cc/pyarrow.h/pyarrow_api.h——PyArrow C API 的入口import_pyarrow()注册机制extension_type.cc、udf.cc、inference.cc、io.cc、ipc.cc、datetime.cc、decimal.cc等——扩展类型、自定义函数、类型推断、IO 与 IPC 的 C 支撑config.cc/common.cc——构建期配置与公共工具BuildInfo、CppBuildInfo等运行时信息最终经由此层暴露到 Python。这层代码由构建系统与 C 核心库一起编译includes/libarrow_python.pxd负责把它声明给 Cythonlib.pyx与*.pxi再把它用起来——三层之间的分工与文档描述严格一致。从源码结构看一次典型的跨层调用链把四层串起来一次用户调用的路径大致是用户调用pyarrow包中*.py层声明的函数调用落到 Cython 编译的pyarrow.liblib.pyx*.pxi或某个_*.pyx模块Cython 代码经由includes/*.pxd的声明直接调用 libarrow / PyArrow C 的 C 函数通常在nogil段中执行PyArrow C如ConvertPySequence完成类型推断与内存转换返回CStatus/Result与shared_ptr包装的 C 对象结果经pyarrow_wrap_*一类辅助函数转回 Python 对象返回给用户。对于想深入阅读或贡献 PyArrow 的开发者这条调用链是定位问题的地图API 行为与文档字符串看*.pyPython 对象与 C 对象的转换边界看*.pxi/_*.pyxC 符号声明看includes/*.pxdNumPy/pandas 转换与 C 侧回调看 python/pyarrow/src/arrow/python/。若排查构建或版本问题pyarrow.show_versions()init.py会打印包类型、Arrow C 库版本、编译器与 git 修订号等构建信息可直接定位到是哪一层、哪次构建的产物。小结PyArrow 是 Arrow C 的 Pythonic 封装*.py声明用户 APIlib.pyx*.pxi暴露核心库能力内部实现_*.pyx提供子系统胶水代码includes/*.pxd原样声明 C APIsrc/arrow/python提供 NumPy/pandas 转换与 Python 对象回调等低层支撑。参与社区的路径订阅dev-subscribearrow.apache.org邮件列表、跟踪 GitHub issue、研读 format/ 下的 FlatBuffers 格式规范。各层文件与文档描述的对应关系均可在仓库中直接验证建议以本文给出的相对路径为起点逐层阅读。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表