资讯动态

Apache Arrow 贡献实战:从零为 PyArrow compute 模块添加新功能的完整教程

发布时间:2026/9/14 15:47:06 来源:尧图企业网站定制
Apache Arrow 贡献实战从零为 PyArrow compute 模块添加新功能的完整教程【免费下载链接】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 教程为主线手把手演示如何为 PyArrow 的arrow.compute模块贡献一个新功能模仿现有pc.min_max聚合函数、但把区间两端各扩宽 1 的pc.tutorial_min_max。教程覆盖从 fork 仓库、构建 PyArrow、创建 GitHub issue、写实现与单元测试到运行 pytest、pre-commit 风格检查、提交并创建 Pull Request 的完整贡献流程同时结合当前仓库中的源码python/pyarrow/compute.py、python/pyarrow/_compute.pyx、python/pyarrow/tests/test_compute.py与 C 内核实现cpp/src/arrow/compute/kernels/aggregate_basic.cc说明 PyArrow 函数从 C 内核到 Python 包装的调用链路帮助读者掌握一次可复用的开源贡献完整流程。教程背景与目标本教程来自仓库中的官方开发者指南文档 docs/source/developers/guide/tutorials/python_tutorial.rst它是 Apache Arrow 开发者指南的组成部分与 快速参考指南 和 Step-by-step 贡献指南 配套后两者讲解通用流程而本教程针对一个具体案例逐段走完。我们要完成的功能贡献落在 PyArrow 的 compute 模块即pyarrow.computePython 中常简写为pc。这个流程同样适用于修 bug 或新增语言绑定。教程中要实现的tutorial_min_max是一个为教学目的虚构的函数它模仿已有的pc.min_max但把输出区间两端各扩宽 1。虽然函数本身是虚构的但整个贡献流程、源码定位方法、测试与 PR 步骤在真实贡献中完全通用。目标行为对输入[4, 5, 6, None, 1]pc.min_max返回[(min, 1), (max, 6)]而pc.tutorial_min_max返回[(min-, 0), (max, 7)]。空值行为当skip_nullsFalse即把空值纳入计算时结果与pc.min_max一致返回[(min, None), (max, None)]。环境准备fork 并克隆仓库假设 Git 已安装。首先在 GitHub 上 fork Apache Arrow 仓库fork 会生成一份你名下的副本后续用于提交分支然后克隆并关联上游$ git clone https://github.com/your username/arrow.git $ cd arrow $ git remote add upstream https://github.com/apache/arrow这里origin指向你自己的 forkupstream指向官方主仓库。之后所有同步官方最新代码的操作都通过upstream完成。构建 PyArrow不同操作系统上构建 PyArrow 的脚本不同因此本教程只给出构建环节的指引不逐行贴出各平台脚本构建流程的入门介绍见 构建 Arrow 指南PyArrow 的具体构建步骤见 构建 PyArrow 中的 Python 章节。在当前仓库中与构建相关的脚本集中在 ci/scripts如 ci/scripts/python_build.shPython 侧构建配置见 python/CMakeLists.txt 与 python/pyproject.toml。构建完成后从arrow/python目录进入 Python 控制台即可使用本地产出的pyarrow模块。为功能创建 GitHub issue新功能需要先有 issue 登记避免与其他人重复工作。步骤使用 GitHub 账号登录进入 Apache Arrow 的 GitHub issues 页面点击New issue在 issue 中清晰描述要添加的功能本教程中即模仿pc.min_max但区间各扩宽 1 的教学函数在 issue 下添加一条take评论表示你认领该 issue让其他贡献者知道你在处理。更多关于 issue 的使用规范见开发者指南的 寻找与认领 issue 部分。从最新的 main 分支创建工作分支在动手写代码前先把本地 main 同步到官方最新并基于它切出新分支教程使用历史上对应的 issue 号命名分支ARROW-14977现在 Arrow 使用 GitHub issue分支命名可沿用类似约定例如GH-14977$ git checkout main $ git fetch upstream $ git pull --ff-only upstream main $ git checkout -b ARROW-14977研究现有实现定位pc.min_max写新功能前先在仓库中调研pc.min_max是如何定义并与 C 关联的。在 GitHub 上搜索定位可以在 Apache Arrow 仓库的 GitHub 界面用搜索框查找pc.min_max的函数引用然后在pyarrow文件夹下搜索test_compute.py文件可以看到该函数被测试的位置。从搜索结果可以推断函数在 python/pyarrow/tests/test_compute.py 中被测试因此定义在compute.py文件中。提示当某个 API 的文档还不完善时单元测试是很好的代码示例来源——它们展示了真实、可运行的调用方式。用 Python 控制台做交互式研究从arrow/python目录进入 Python 控制台直接观察pc.min_max的行为$ cd python $ python Python 3.9.7 (default, Oct 22 2021, 13:24:00) [Clang 13.0.0 (clang-1300.0.29.3)] on darwin Type help, copyright, credits or license for more information. import pyarrow.compute as pc data [4, 5, 6, None, 1] data [4, 5, 6, None, 1] pc.min_max(data) pyarrow.StructScalar: [(min, 1), (max, 6)] pc.min_max(data, skip_nullsFalse) pyarrow.StructScalar: [(min, None), (max, None)]可以看到默认skip_nullsTrue时跳过空值返回(min1, max6)skip_nullsFalse时遇到空值整体返回None。在 python/pyarrow/tests/test_compute.py#L781-L812 的test_min_max中可以找到更完整的调用矩阵def test_min_max(): # An example generated function wrapper with possible options data [4, 5, 6, None, 1] s pc.min_max(data) assert s.as_py() {min: 1, max: 6} s pc.min_max(data, optionspc.ScalarAggregateOptions()) assert s.as_py() {min: 1, max: 6} s pc.min_max(data, optionspc.ScalarAggregateOptions(skip_nullsTrue)) assert s.as_py() {min: 1, max: 6} s pc.min_max(data, optionspc.ScalarAggregateOptions(skip_nullsFalse)) assert s.as_py() {min: None, max: None} # Options as dict of kwargs s pc.min_max(data, options{skip_nulls: False}) assert s.as_py() {min: None, max: None} # Options as named functions arguments s pc.min_max(data, skip_nullsFalse) assert s.as_py() {min: None, max: None} ...PyArrow 函数的三层架构从源码结构可以梳理出pc.min_max的完整调用链C 内核层真正的计算实现在 C。在 cpp/src/arrow/compute/kernels/aggregate_basic.cc#L987-L1144 中注册了名为min_max的ScalarAggregateFunction并为其挂载了覆盖null、boolean、数值类型、时间类型、二进制类型、固定长度二进制、INTERVAL_MONTHS、DECIMAL128、DECIMAL256等多种输入类型的 kernel还根据 CPU 能力选择性启用 AVX2/AVX512 加速实现。Cython 绑定层PyArrow 用 Cython 把 C 内核包装为 Python 可调用的对象。函数注册表、call_function、FunctionOptions及各类选项类包括ScalarAggregateOptions都在 python/pyarrow/_compute.pyx 中实现。其中call_function(name, args, optionsNone, ...)通过_global_func_registry.get_function(name)查表并调用见 python/pyarrow/_compute.pyx#L588-L611。Python 包装层python/pyarrow/compute.py 从pyarrow._compute导入各类函数与选项类见文件开头 python/pyarrow/compute.py#L18-L80并提供高层pc.*便捷 API。文档字符串的自动补充也定义在 python/pyarrow/_compute_docstrings.py其中 min_max 的示例文档 演示了skip_nulls与min_count的用法。我们要添加的新函数定义在compute.py文件末尾本质上是一个纯 Python 包装函数调用 C 的min_max内核再对返回的StructScalar做后处理。ScalarAggregateOptions是聚合函数共享的选项类其 Cython 实现见 python/pyarrow/_compute.pyx#L1623-L1638接受两个关键字参数参数类型默认值含义skip_nullsboolTrue为True时忽略输入中的空值为False时遇到空值则整体返回Nonemin_countint1非空值的最小数量低于该值则返回Nonemin_count0时即使输入为空也返回聚合值第一步实现先打通 C 调用在 python/pyarrow/compute.py 末尾添加第一版试探性代码验证对 Cmin_max的调用通路def tutorial_min_max(values, skip_nullsTrue): Add docstrings Parameters ---------- values : Array Returns ------- result : TODO Examples -------- import pyarrow.compute as pc data [4, 5, 6, None, 1] pc.tutorial_min_max(data) pyarrow.StructScalar: [(min-, 0), (max, 7)] options ScalarAggregateOptions(skip_nullsskip_nulls) return call_function(min_max, [values], options)重新导入pyarrow.compute验证 import pyarrow.compute as pc data [4, 5, 6, None, 1] pc.tutorial_min_max(data) pyarrow.StructScalar: [(min, 1), (max, 6)]调用通了——目前返回的仍是原生min_max的结果(min1, max6)说明ScalarAggregateOptions(skip_nulls...)与call_function(min_max, [values], options)的组合是正确入口。接下来要做的是把区间两端各扩宽 1。研究 StructScalar 的构造方式为了把(min1, max6)变成(min-0, max7)需要构造一个带自定义字段名的pyarrow.StructScalar。在 python/pyarrow/tests/test_scalars.py 的test_struct_duplicate_fields测试中可以看到StructScalar的构造示例。也可以在控制台自行验证 import pyarrow as pa ty pa.struct([ ... pa.field(min-, pa.int64()), ... pa.field(max, pa.int64()), ... ]) pa.scalar([(min-, 3), (max, 9)], typety) pyarrow.StructScalar: [(min-, 3), (max, 9)]关键知识点用pa.struct([...])定义包含字段名与类型的 schema再用pa.scalar([(field_name, value), ...], typety)构造StructScalar。对已有StructScalarscalar[i]按位置取子标量as_py()把标量转为 Python 原生对象。完成实现扩展 min/max 区间结合对StructScalar的新认识完成最终实现def tutorial_min_max(values, skip_nullsTrue): Compute the minimum-1 and maximum1 values of a numeric array. This is a made-up feature for the tutorial purposes. Parameters ---------- values : Array skip_nulls : bool, default True If True, ignore nulls in the input. Returns ------- result : StructScalar of min-1 and max1 Examples -------- import pyarrow.compute as pc data [4, 5, 6, None, 1] pc.tutorial_min_max(data) pyarrow.StructScalar: [(min-, 0), (max, 7)] options ScalarAggregateOptions(skip_nullsskip_nulls) min_max call_function(min_max, [values], options) if min_max[0].as_py() is not None: min_t min_max[0].as_py()-1 max_t min_max[1].as_py()1 else: min_t min_max[0].as_py() max_t min_max[1].as_py() ty pa.struct([ pa.field(min-, pa.int64()), pa.field(max, pa.int64()), ]) return pa.scalar([(min-, min_t), (max, max_t)], typety)实现要点拆解min_max call_function(min_max, [values], options)复用 C 内核返回StructScalarmin_max[0]/min_max[1]按位置取出 min 与 max 两个子标量用as_py()转为 Python 值后做-1/1运算注意空值分支不做算术运算否则None - 1会报错最终用pa.structpa.scalar构造带min-、max字段名的StructScalar返回。添加单元测试并运行 pytest在 python/pyarrow/tests/test_compute.py 中添加单元测试def test_tutorial_min_max(): arr [4, 5, 6, None, 1] l1 {min-: 0, max: 7} l2 {min-: None, max: None} assert pc.tutorial_min_max(arr).as_py() l1 assert pc.tutorial_min_max(arr, skip_nullsFalse).as_py() l2运行单个测试用-k指定测试名筛选$ cd python $ python -m pytest pyarrow/tests/test_compute.py -k test_tutorial_min_max test session starts platform darwin -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 rootdir: /Users/alenkafrim/repos/arrow/python, configfile: setup.cfg plugins: hypothesis-6.24.1, lazy-fixture-0.6.3 collected 204 items / 203 deselected / 1 selected pyarrow/tests/test_compute.py . [100%] 1 passed, 203 deselected in 0.16s 再运行整个测试文件确保没有破坏既有行为$ python -m pytest pyarrow/tests/test_compute.py test session starts platform darwin -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 rootdir: /Users/alenkafrim/repos/arrow/python, configfile: setup.cfg plugins: hypothesis-6.24.1, lazy-fixture-0.6.3 collected 204 items pyarrow/tests/test_compute.py ................................... [ 46%] ................................................. [100%] 204 passed in 0.49s Arrow 的测试细节参见开发者指南的 测试 部分。除单元测试外PyArrow 的测试约定、pytest 配置位于 python/setup.cfg 与 python/pyarrow/conftest.py。检查代码风格Arrow 使用 pre-commit。提交前对 Python 文件运行$ pre-commit run --show-diff-on-failure --coloralways --all-files python--show-diff-on-failure会在检查失败时展示修复建议的 diff--all-files指定检查全部文件也可只针对本次改动的文件运行。创建 Pull Request检查改动并提交用git status确认改动了哪些文件、只提交本次功能相关的文件$ git status On branch ARROW-14977 Changes not staged for commit: (use git add file... to update what will be committed) (use git restore file... to discard changes in working directory) modified: python/pyarrow/compute.py modified: python/pyarrow/tests/test_compute.py no changes added to commit (use git add and/or git commit -a)用git diff逐行审查改动检查是否有疏漏$ git diff diff --git a/python/pyarrow/compute.py b/python/pyarrow/compute.py index 9dac606c3..e8fc775d8 100644 --- a/python/pyarrow/compute.py b/python/pyarrow/compute.py -774,3 774,45 def bottom_k_unstable(values, k, sort_keysNone, *, memory_poolNone): sort_keys map(lambda key_name: (key_name, ascending), sort_keys) options SelectKOptions(k, sort_keys) return call_function(select_k_unstable, [values], options, memory_pool) def tutorial_min_max(values, skip_nullsTrue): Compute the minimum-1 and maximum-1 values of a numeric array. This is a made-up feature for the tutorial purposes. Parameters ---------- values : Array skip_nulls : bool, default True If True, ignore nulls in the input. Returns ------- result : StructScalar of min-1 and max1 Examples -------- import pyarrow.compute as pc data [4, 5, 6, None, 1] pc.tutorial_min_max(data) pyarrow.StructScalar: [(min-, 0), (max, 7)] options ScalarAggregateOptions(skip_nullsskip_nulls) min_max call_function(min_max, [values], options) ...确认无误后提交并写明清晰、有意义的提交信息$ git commit -am Adding a new compute feature for tutorial purposes [ARROW-14977 170ef85be] Adding a new compute feature for tutorial purposes 2 files changed, 51 insertions()用git log检查提交历史$ git log commit 170ef85beb8ee629be651e3f93bcc4a69e29cfb8 (HEAD - ARROW-14977) Author: Alenka Frim frim.alenkagmail.com Date: Tue Dec 7 13:45:06 2021 0100 Adding a new compute feature for tutorial purposes commit 8cebc4948ab5c5792c20a3f463e2043e01c49828 (main) Author: Sutou Kouhei kouclear-code.com Date: Sun Dec 5 15:19:46 2021 0900 ARROW-14981: [CI][Docs] Upload built documents ...同步与推送如果分支创建已久先 rebase 到上游 main确保没有合并冲突$ git pull upstream main --rebase然后推送到 forkorigin$ git push origin ARROW-14977 Enumerating objects: 13, done. Counting objects: 100% (13/13), done. Delta compression using up to 8 threads Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 1.19 KiB | 1.19 MiB/s, done. Total 7 (delta 6), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (6/6), completed with 6 local objects. remote: remote: Create a pull request for ARROW-14977 on GitHub by visiting: remote: https://github.com/AlenkaF/arrow/pull/new/ARROW-14977 remote: To https://github.com/AlenkaF/arrow.git * [new branch] ARROW-14977 - ARROW-14977创建并完善 PR推送后在 GitHub 的 Apache Arrow 仓库页面主仓库或 fork会看到一条黄色提示条提示分支有最近的推送点击Compare pull request进入创建 PR 的页面标题改为与 issue 匹配的格式。教程创作时 Arrow 使用 Jira issue 追踪器标题形如ARROW-14977: [Python] Add a made-up feature for the guide tutorial注意标题中补上了标点符号当前 Arrow 使用 GitHub issue标题相应改为GH-14977: [Python] Add a made-up feature for the guide tutorial前缀描述写明你试图解决的问题、改动内容与验证方式方便 reviewers 快速理解点击Create pull request创建 PR。PR 之后的协作PR 创建后会关联到对应 issueCI 随即开始运行。之后需要等待 review根据反馈修改代码、回复评论、解决 conversation直到 PR 被合并。关于 PR 生命周期的更多细节参见开发者指南的 PR 生命周期 部分。总结本教程通过一个虚构的pc.tutorial_min_max功能完整走通了 PyArrow compute 模块的贡献链路调研用 GitHub 搜索与 Python 控制台定位pc.min_max的定义与测试位置理解 PyArrow 的C 内核cpp/src/arrow/compute/kernels/aggregate_basic.cc→ Cython 绑定python/pyarrow/_compute.pyx→ Python 包装python/pyarrow/compute.py三层架构实现用ScalarAggregateOptionscall_function(min_max, ...)复用 C 内核再对StructScalar结果做后处理构造自定义字段名的返回值验证在 python/pyarrow/tests/test_compute.py 编写单元测试用 pytest 跑通单测与全量测试用 pre-commit 检查 PEP 8 风格提交流程从 fork、分支、commit、rebase、push 到创建与维护 PR完成一次标准化的开源贡献。即使这个函数本身是教学虚构的这套定位源码 → 复用内核 → 包装 API → 测试 → 提交 PR的方法论可直接迁移到任何真实的 Arrow 功能开发、Bug 修复或语言绑定工作中。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价