【免费下载链接】spark
Apache Spark – A unified analytics engine for large-scale data processing
项目地址:
https://gitcode.com/gh_mirrors/sp/spark
点击查看 免费下载
Apache Spark 是一个统一的大规模数据处理分析引擎,PySpark 作为其 Python 接口,贡献方式涵盖发布版测试、文档编写、代码改动、错误报告、JIRA 维护与代码评审等多种类型。本文基于 python/docs/source/development/contributing.rst 整理 PySpark 特有的贡献规范与实操流程,并对照仓库源码逐项印证。读完本文,你将掌握:如何安装 Release Candidate 参与发布前测试、如何用 Sphinx/Jekyll 构建与验证文档、如何搭建 Conda/venv/pip 开发环境、如何编写符合规范的类型标注与代码/文档字符串/doctest、以及如何基于 error-conditions.json 与 PySparkException 体系贡献标准化的错误与异常。
一、贡献概览:PySpark 不止于写代码
Apache Spark 的通用贡献说明参见官方总指南(spark.apache.org/contributing.html),包括帮助其他用户、测试发布版本、评审改动、文档贡献、缺陷报告、JIRA 维护、代码改动等。本文页面聚焦 PySpark 的额外细节,其中最具 PySpark 特色的三条路径是:
- 测试发布版本(Release Candidate, RC):官方发布前在 dev@spark.apache.org 邮件列表发起投票,任何用户都可以安装 RC 并验证自己的既有工作负载;
- 文档贡献:PySpark 的发布文档由 Sphinx 生成,与 Spark 主站 Jekyll 文档相互独立;
- 代码与错误体系贡献:代码需遵循 Pythonic 风格并与 Scala/Java API 对齐,抛错必须走标准化的 error class 体系而非任意错误消息。
仓库中 PySpark 开发文档的完整入口在 python/docs/source/development/index.rst,其中 contributing、testing、debugging、setting_ide、logger、errors 六个页面共同构成开发者文档体系。
二、通过测试发布版本贡献力量
2.1 安装 Release Candidate
官方在正式发布前会将候选版本发布到 dev@spark.apache.org 邮件列表并开启投票。候选版本可通过 pip 直接安装,例如 Spark 3.0.0 RC1:
pip install https://dist.apache.org/repos/dist/dev/spark/v3.0.0-rc1-bin/pyspark-3.0.0.tar.gz
具体的发布文件链接(形如 https://dist.apache.org/repos/dist/dev/spark/v3.0.0-rc1-bin)会在投票线程中给出。
2.2 为什么测试 RC 是重要贡献
用用户自己的既有工作负载对候选版本做回归验证,是在正式发布前阻止破坏性变更流入用户环境的关键手段。一旦发现回归(regression)、正确性问题或足够严重的性能退化,社区通常会弃用该候选版本,集中修复后纳入下一个 RC。因此,RC 测试是最直接也最容易被低估的贡献方式——它不需要写代码,只需要真实业务场景。
三、贡献文档变更
3.1 Spark 主站文档与 PySpark 文档的分工
Spark 的发布文档位于仓库根目录的 docs 目录,其构建方式与依赖在 docs/README.md 中有说明。在 docs/ 目录下执行以下命令即可在本地启动文档服务,跳过 Scala/R/SQL 文档以加快速度:
SKIP_SCALADOC=1 SKIP_RDOC=1 SKIP_SQLDOC=1 bundle exec jekyll serve –watch
而 PySpark 自身的发布文档由 Sphinx 生成,代码位于 python/docs,构建方式完全独立。仅构建 PySpark 文档时,进入 python/docs 目录执行:
make html
生成的 HTML 位于 python/docs/build/html。仓库中的 python/docs/Makefile 显示其默认参数为 SPHINXOPTS ?= "-W" "-j" "4",即以“警告即错误”的严格模式并行构建,且通过 export PYTHONPATH=$(realpath ..):$(realpath ../lib/py4j-0.10.9.9-src.zip) 将 pyspark 包与 py4j 源码 zip 加入导入路径,因此新增/修改 API 的文档后,必须先保证本地 make html 干净通过。
3.2 新 API 必须手动登记到 reference
一个容易被忽略的硬性要求:新加的 API 必须手动添加到 python/docs/source/reference 下对应的 RST 文件中,否则即便代码注释(docstring)完整,也不会出现在 PySpark 发布文档中。仓库中的 python/docs/source/reference/index.rst 及 python/docs/source/reference/pyspark.errors.rst 等文件即承担着这一“API 清单登记”职责,文章引用的 API 若想被自动索引,也需在对应 .rst 中显式声明。
四、准备代码贡献
开始写 PySpark 代码前,除阅读官方通用指南外,还需牢记以下 PySpark 特有原则:
- Be Pythonic:遵循《The Zen of Python》(PEP 20);
- 与 Scala/Java 侧 API 对齐:Spark 是统一引擎,各语言 API 层保持一致;
- 允许 PySpark 特有 API:只要 Pythonic 且不与既有 API 冲突,就可以提出新 API 请求,例如 UDF 的装饰器用法;
- 修改/扩展公共 API 时必须同步调整类型标注:详见“六、贡献与维护类型标注”。
4.1 pandas API on Spark 的三条设计原则
如果修复 pyspark.pandas 包,请遵循以下设计原则(源码目录见 python/pyspark/pandas):
原则一:大数据返回 pandas-on-Spark 结构,小数据返回 pandas 结构。
开发者常纠结某函数应返回 pandas-on-Spark 的 DataFrame/Series 还是 pandas 结构。判定标准是结果规模:结果可能很大就用 pandas-on-Spark;结果必然很小就用 pandas。例如 DataFrame.dtypes 返回 pandas Series(列数有界且很小),而 DataFrame.head() 或 Series.unique() 返回 pandas-on-Spark 结构(结果可能很大)。
原则二:为常见数据科学任务提供可发现的 API。
pandas 偏“为常见任务提供 API”,Spark 传统上偏“提供抽象、由用户组合原语”。举例:value_counts 是最常见的数据科学操作之一,pandas 的 DataFrame.value_counts() 默认排序,90% 的探索场景下用户正需要它;而 Spark 的不排序更适合构建数据管道(用户可通过显式 orderBy 获得 pandas 行为)。pandas API on Spark 应更靠拢 pandas 风格,为常见任务提供开箱即用的可发现 API——多数情况下直接实现 pandas API 即可,但像“大数据的绘图”这类 pandas 未覆盖的需求,则可以补充 Spark 自己的实现。
原则三:内置防护栏,防止用户在数据规模放大时“搬起石头砸自己的脚”。
pandas 中某些操作随数据规模增长会变得代价高昂,不能给用户留下“在 pandas API on Spark 中也能放心依赖”的错觉。因此以下能力不实现:
- 本质上无法并行化的能力,例如逐元素命令式循环;
- 要求把整个工作集物化到单节点内存的能力。这是不实现 pandas.DataFrame.to_xarray 的原因;_repr_html_ 将展示的记录数上限设为 1000,也是为了防止用户在 notebook 里敲一下 DataFrame 名字就打爆 driver 节点。
少数例外服务于“大数据科学”的常见模式:初始数据集大,但分析深入后工作集会变小。典型如数据科学家对数据集做聚合后希望转为本地结构,为此提供了:
- DataFrame.to_pandas:返回 pandas DataFrame(仅 pandas API on Spark 提供);
- DataFrame.to_numpy:返回 numpy 数组,pandas 与 pandas API on Spark 均可用。
这些函数从命名上就明确表示返回的是本地结构、需将数据物化进单节点内存,因此文档中也都显式标注了“结果必须很小”的警告。
五、环境搭建(Prerequisite 与三种方式)
5.1 前置条件
PySpark 开发需要先构建 Spark(需要合适的 JDK),详见《Building Spark》指南。需要注意:
- 若打算为 **Spark Connect(Python 侧)**贡献代码,还需要安装 buf(Protobuf 工具链);
- 安装依赖要求 pip >= 25.1,旧版本请先升级:
pip install –upgrade pip
仓库中的 pyproject.toml 定义了 –group dev 所安装的开发依赖组,pip install –upgrade –group dev 会按该配置安装开发所需依赖。
5.2 方式一:Conda
# Python 3.11+ 是必需的
conda create –name pyspark-dev-env python=3.11
conda activate pyspark-dev-env
pip install –upgrade –group dev
每次开始开发前记得切换回该环境:
conda activate pyspark-dev-env
之后就可以开始开发并运行测试(测试指南见 python/docs/source/development/testing.rst)。
5.3 方式二:venv
使用 Python 内置的 venv 模块创建隔离环境:
# Python 3.11+ 是必需的
python3 -m venv .venv
source .venv/bin/activate
pip install –upgrade –group dev
5.4 方式三:纯 pip
Python 3.11+ 下可直接安装:
pip install –upgrade –group dev
三种方式殊途同归:都要求 Python 3.11+ 与 pip 25.1+,最终统一通过 pip install –upgrade –group dev 装配开发依赖。构建 Spark 后即可运行测试,仓库 python/run-tests 脚本负责测试编排。
六、贡献与维护类型标注
6.1 基本规则
PySpark 的类型标注是内联(inlined)的,以便充分享受静态类型检查。默认只为公共 API 标注,且标注应尽量满足:
@overload
def __init__(
self,
*,
threshold: float = …,
inputCol: Optional[str] = …,
outputCol: Optional[str] = …
) -> None: …
@overload
def __init__(
self,
*,
thresholds: Optional[List[float]] = …,
inputCols: Optional[List[str]] = …,
outputCols: Optional[List[str]] = …
) -> None: …
6.2 复杂辅助类型放 .pyi stub
复杂的支撑类型定义应放入专门的 _typing.pyi 存根文件中,仓库中的实例是 python/pyspark/sql/_typing.pyi。
6.3 校验方式
可以用 dev/lint-python 脚本校验标注,也可以直接调用 mypy:
mypy –config python/mypy.ini python/pyspark
python/mypy.ini 是 PySpark 的 mypy 配置文件,dev/lint-python 是仓库统一的 Python 静态检查脚本(见 dev/lint-python),它同时驱动下文提到的 pycodestyle 与 ruff。
七、代码与文档字符串规范
7.1 代码规范(Code Conventions)
请跟随既有代码库的风格:基本等同于 PEP 8,但每行长度上限是 100 字符而非 79。命名方面还有三条约定:
- 与 Scala/Java 对齐的公共 API 使用 camelCase(与 Python 标准库 threading 类似,其 API 本身也受 Java 启发);
- 与之相对,functions.py 使用 snake_case,以便 API 对 SQL(及 Python)更友好;
- pandas-on-Spark(pyspark.pandas)也用 snake_case,因为这个包不受“与其他语言 API 一致”的约束。
PySpark 使用 pycodestyle 与 ruff 两类 linter,均由 dev/lint-python 驱动执行,因此提交前务必运行该脚本复查。
7.2 文档字符串规范(Docstring Conventions)
PySpark 遵循 NumPy 文档风格(numpydoc)。
7.3 Doctest 规范
doctest 应按逻辑分组,组间以空行分隔。例如第一个块放准备语句、第二个块演示某个参数的用法、第三个块演示另一个参数(可参考 pandas 的 DataFrame.rsub 文档示例)。PySpark doctest 应保持这种一致的块划分;当 doctest 覆盖不足或示例数量不够时,应主动补充更多 doctest。
八、贡献标准化的错误与异常
8.1 为什么必须走 error class 体系
向用户抛出标准化的错误或异常时,开发者应指定 error class 与消息参数,而不是写任意错误消息。仓库中的错误条件定义在 python/pyspark/errors/error-conditions.json(约 1258 行、上百个条目),运行时由 python/pyspark/errors/error_classes.py 读取——它用 importlib.resources 加载 JSON 并构建 ERROR_CLASSES_MAP 供全局使用。异常基类实现在 python/pyspark/errors/exceptions/base.py,其中的 PySparkException 是所有 PySpark 错误异常的基类。
8.2 标准贡献流程(五步)
8.3 改造前后对比
改造前:抛出任意错误消息——
raise ValueError("Problem A because B")
改造后:先在 error-conditions.json 中定义模板——
"PROBLEM_BECAUSE": {
"message": ["Problem <problem> because <cause>"]
}
在 exceptions.py 中定义异常类——
class PySparkTestError(PySparkException):
def __init__(self, errorClass: str, messageParameters: Dict[str, str]):
super().__init__(errorClass=errorClass, messageParameters=messageParameters)
def getMessageParameters(self) -> Optional[Dict[str, str]]:
return super().getMessageParameters()
最后用 error class 和消息参数抛出——
raise PySparkTestError("PROBLEM_BECAUSE", {"problem": "A", "cause": "B"})
8.4 访问错误字段
捕获继承自 PySparkException 的异常后,用 getCondition() 读取 error class(从 python/pyspark/errors/exceptions/base.py 的实现可见,getCondition() 自 4.0.0 起成为标准接口,旧的 getErrorClass() 已标记弃用并转发到 getCondition();getMessage() 会输出 [{condition}] {message} 形式的完整消息):
try:
…
except PySparkException as pe:
if pe.getCondition() == "PROBLEM_BECAUSE":
…
除 getCondition() / getMessage() 外,PySparkException 还提供 getMessageParameters()(消息参数字典)与 getSqlState()(SQLSTATE 字符串,无对应值时返回 None)。
8.5 字段与不变量
Error class(错误类):是错误类别的简洁、人类可读表示。无法归类的错误可分配带 _LEGACY_ERROR_TEMP_ 前缀和未使用序号的传统类,例如 _LEGACY_ERROR_TEMP_0053。其不变量包括:
- 唯一;
- 跨版本稳定(consistent across releases);
- 按字母序排列。
Message(消息):提供可读的错误描述,消息格式通过 C 风格 printf 语法接收字符串参数,质量须符合 Apache Spark Error Message Guidelines。其不变量为:唯一。
从仓库实测看,error-conditions.json 中的条目除 message 外还支持 sqlState 字段(例如 ATTRIBUTE_NOT_SUPPORTED 关联 "sqlState": "0A000"),PySparkException.getSqlState() 即据此返回;开发者新增条目时可参考既有模式,让错误同时携带 SQL 状态信息,便于 JDBC 等场景识别。错误体系的测试覆盖在 python/pyspark/errors/tests/test_errors.py 中,可在新增错误类后据此补充测试。
九、下一步:构建与测试
环境就绪后,测试相关细节可继续阅读 python/docs/source/development/testing.rst。简要预告其核心流程:先通过 Maven 或 SBT 构建 Spark(例如 build/mvn -DskipTests clean package 或 build/sbt -Phive clean package),再运行 python/run-tests –python-executable=python3;单测可用 python/run-tests –testnames pyspark.sql.tests.test_arrow 精确指定;若修改了 Spark Connect 的 Protobuf 定义,则需先执行 dev/connect-gen-protos.sh 重新生成 Python Protobuf 客户端;调试单个测试时可直接在测试代码中插入 breakpoint() 进入交互式 pdb 会话。
结语
PySpark 的贡献路径多样且规范清晰:参与 RC 投票测试能直接影响发布质量;文档贡献有独立的 Sphinx 构建链路与 API 登记要求;代码贡献强调 Pythonic、API 对齐与 pandas-on-Spark 的三条设计原则;类型标注、代码/docstring/doctest 规范均有明确可执行的检查命令;错误体系则以 error-conditions.json + PySparkException 为核心,用“查重→登记→继承→混入→抛出”五步流程保证错误消息的唯一、稳定与可编程访问。对照仓库源码,上述每一条规范都有真实实现与测试背书,可直接作为在 Apache Spark 中贡献 PySpark 的落地清单。
赞
【免费下载链接】spark
Apache Spark – A unified analytics engine for large-scale data processing
项目地址:
https://gitcode.com/gh_mirrors/sp/spark
点击查看 免费下载
相关推荐
如何彻底清理HeyGem.ai系统痕迹:三阶段完整指南
TensorNetwork收缩算法深度剖析:bucket、greedy和optimal策略对比
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考







