
先说明一下这个标题看着简单真做起来能劝退不少人。网上搜“Windows spark 搭建”清一色是 Linux 或 Mac 教程偶尔蹦出一篇 Windows 的还写得云里雾里照着抄经常卡在某一步直接进行不下去。我前前后后在 Windows 上把 Spark 环境从零到跑通折腾了好几遍中间踩过的坑、绕过的弯路、查过的源码报错整理成一篇能直接照着操作的文章。目标就一个让你在 Windows 上用 Python 调 Spark不再被环境问题劝退。1. 环境搭建逻辑拆解先搞懂 Windows 上跑 Spark 为什么格外折腾1.1 Windows 不是 Spark 的“主战场”但这不代表不能好好用Spark 本身是 JVM 系的大数据计算框架官方支持 Linux 和 macOS 是一等公民Windows 属于“能跑但没人替你擦屁股”的状态。很多新手一上来就踩坑根本原因是不了解 Windows 上跑 Spark 的底层依赖链。一个标准的 PySpark 运行链路是这样的Python 代码 (PySpark API) ↓ Spark Driver JVM 进程 ↓ 调用 Spark Core / SQL / MLlib 等组件 ↓ 通过 Hadoop 文件系统接口读写数据这条链路上有四个关键角色JavaSpark 跑在 JVM 上没有 JDK 一切免谈。Spark 本体提供核心计算引擎和 PySpark 的桥接层。Hadoop 相关组件Spark 读写 HDFS、本地文件时依赖 Hadoop 的客户端库在 Windows 上还需要一个特殊的“补丁”程序。Python 环境PySpark 本质是 Python 调 JVMPython 版本必须和 Spark 兼容。所以说Windows 上搭 Spark 不是“装一个软件”的事而是要同时伺候好四个组件。任何一个版本对不上、环境变量没配好都会以各种奇怪的报错形式反馈给你。1.2 为什么官网教程在 Windows 上频频失效我见过太多人照着 Spark 官方 Quick Start 跑结果第一步就卡住。原因主要有三条第一官方文档默认你用的是 Linux/macOS。比如启动 pyspark 时用的./bin/pyspark在 Windows 上根本没有这个 shell 脚本得用bin\pyspark.cmd。文档里写spark-shellWindows 上对应的是bin\spark-shell.cmd。这种细节到处都有不熟悉的人很难意识到。第二Hadoop 在 Windows 上的“水土不服”。Spark 下载页面里提供的“Pre-built for Apache Hadoop”压缩包里面的本地库文件winutils.exe和hadoop.dll是缺失的。没有这个补丁Spark 读写本地文件时轻则报警告重则直接报java.io.IOException: Could not locate executable null\bin\winutils.exe。这是 Windows 用户特有的第一道坎。第三环境变量和 Python 解释器的关联。PySpark 启动时需要找到 Python 解释器需要配置PYSPARK_PYTHON等变量否则可能默认调用系统里某个不是你预期的 Python等报错的时候已经晚了。我们要做的就是把这条链路上的每个环节都打通并且理解为什么这么配这样遇到问题才知道去哪排查。2. 版本选型这一步定生死照着选最省心版本选择是 Windows 上搭 PySpark 最容易翻车的环节。Java、Python、Spark、Hadoop 之间存在兼容矩阵不是随便拉一个最新版就能用的。2.1 核心组件版本对照表我实测下来比较稳定的组合是组件推荐版本说明Java JDK8u202 或 11Spark 3.x 官方支持 Java 8/11/178u202 是 Oracle JDK 8 的最后免费商用版本Python3.8 - 3.10太高版本的 Python 可能出现新版语法兼容问题Spark3.3.x 或 3.4.x这两个大版本最成熟稳定对 Windows 兼容性好Hadoop Client3.3.4 或 3.3.6用于 winutils.exe 补丁和底层 HDFS APIwinutils.exe需要单独下载对应 Hadoop 版本匹配特殊说明一下Java 版本的兼容性这是最容易出问题的点。Spark 3.2 以上对 Java 17 是支持的但很多第三方库比如某些老版本的 Hive、Hadoop 组件并不兼容 Java 17。如果你后面要跑 Spark SQL 集成 HiveJava 8 是最稳妥的选择。所以我个人推荐JDK 8没特殊需求不要上 11 或 17。2.2 为什么我不推荐直接用最新版很多人的习惯是“能下多新下多新”在大数据生态里这是个误区。举几个实际会发生的问题Spark 4.x 预览版刚出来时PySpark 对 Python 3.12 的支持还不完善装完以后各种 undefined symbol 报错。Hadoop 3.4 的 winutils.exe 很难找配套版本网上很多资源对不上号。新版本对 CPU 指令集和内存要求更高Windows 笔记本跑起来风扇狂转体验很差。选版本时记住一个原则选“被验证过半年以上”的组合而不是“最新”的组合。大数据这种东西稳定性永远优先。按上面表格里的组合我在自己的 Windows 11 和公司 Win10 电脑上都跑通了包括 PySpark DataFrame 计算、Spark SQL 查询都没问题。2.3 下载地址和选择细节需要准备的东西如下不要用浏览器默认下载建议用 IDM 或迅雷这类工具Spark 压缩包动辄几百 MB断点续传能救你命JDK 8u202Oracle 官网能下到需要注册 Oracle 账号。嫌麻烦的用 OpenJDK 8Adoptium 发行版也一样亲测没问题。Spark 3.3.2官方下载页面选择 “Pre-built for Apache Hadoop 3.3.4” 这个包注意不要选 “Without Hadoop” 的版本那个还要自己配 Hadoop 环境新手容易懵。winutils.exeGitHub 上有对应版本的 winutils 库下载 Hadoop 3.3.x 对应的版本。这个文件缺失是 Windows 上跑 Spark 的经典报错来源。Python 3.9官网下载安装时务必要勾选 “Add Python to PATH”这个细节省去后面很多麻烦。提示有人会问“我不下载 Hadoop 发行版行不行”答案是行因为 Spark 的 pre-built 包已经自带 Hadoop client 的 jar 依赖了你只需要下载 winutils.exe 和 hadoop.dll 这两个文件来“骗过”本地的 native 接口。这也是 Windows 上搭建比 Linux 多出来的一个特殊步骤。3. 全流程实操记录从零到 PySpark 跑通第一个任务下面是我的完整操作过程每一步都给了验证方式建议顺着往下走不要跳步骤。3.1 第一步JDK 安装与环境变量验证JDK 安装很常规重点是环境变量配置。按Win R输入sysdm.cpl打开系统属性 → 高级 → 环境变量新建系统变量变量名JAVA_HOME变量值填你 JDK 的实际路径C:\Program Files\Java\jdk1.8.0_202然后编辑Path变量在开头或结尾新增一行%JAVA_HOME%\bin配置完以后务必重新打开一个 CMD 窗口输入java -version看到类似下面的输出说明 JDK 配置成功java version 1.8.0_202 Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)如果系统提示“不是内部或外部命令”说明Path没配好或者 CMD 没重开先把这两个原因排除。3.2 第二步Spark 解压与目录规划把下载的 Spark 压缩包解压到一个路径中不含空格和中文的目录。这一步很多人不在意结果后面各种诡异报错。我习惯统一放在D:\bigdata\spark-3.3.2-bin-hadoop3目录结构大致如下spark-3.3.2-bin-hadoop3 ├── bin # pyspark、spark-shell 等命令 ├── conf # 配置文件 ├── data # 自带的一些样例数据 ├── jars # Spark 的全部依赖包 ├── python # PySpark 的 Python 端源码 ├── R # R 语言支持 ├── sbin # 集群管理脚本 └── yarn # YARN 集成文件有人会把 Spark 放在C:\Program Files下面强烈不建议。这个路径带空格Spark 脚本解析路径时偶尔会出问题虽然大多数情况没事但一旦报错排查起来非常折磨人。配置环境变量变量名SPARK_HOME 变量值D:\bigdata\spark-3.3.2-bin-hadoop3同时在Path里新增%SPARK_HOME%\bin3.3 第三步winutils.exe 补丁Windows 特有的坑这是 Windows 用户独有的步骤Linux 和 Mac 不用管。下载完对应版本的 winutils 后把winutils.exe放到一个固定目录比如D:\bigdata\hadoop-bin\bin\winutils.exe注意这个路径是可以自定义的但建议放在 Hadoop 相关的目录结构下方便后续统一管理。然后在环境变量里新增变量名HADOOP_HOME 变量值D:\bigdata\hadoop-binwinutils.exe必须放在%HADOOP_HOME%\bin目录下Spark 启动时会去这个路径找它。没有这个文件Spark 任务启动后访问本地文件系统时会直接报错。验证方式重新打开 CMD执行winutils.exe正常情况会输出使用帮助信息说明这个文件可以被系统调用。3.4 第四步安装 Python 与 PySpark这部分有一个很大的认知误区要纠正PySpark 不是独立安装的第三方包而是 Spark 自带 Python API 的封装。也就是说你需要先安装 Spark 本体然后通过 pip 安装pysparkpip 包只是一个 Python 端的桥接层。Python 安装完成后在 CMD 里执行python --version pip --version确认 Python 可用。然后安装 PySpark注意版本号要和你下载的 Spark 大版本一致Spark 3.3.2 对应 pyspark 3.3.2不要装 4.x 或其他版本。pip install pyspark3.3.2装完以后验证pip show pyspark输出信息显示版本为 3.3.2位置在 site-packages这就说明 PySpark 的 Python 端装好了。配置 Python 环境变量变量名PYSPARK_PYTHON 变量值python如果系统里只有一个 Python配python就能找到。如果你有多个 Python 环境这里要填完整路径比如C:\Users\yourname\AppData\Local\Programs\Python\Python39\python.exe3.5 第五步首次启动验证在 CMD 里输入pyspark正常情况下你会看到一堆日志最后进入一个类似这样的交互式界面Welcome to ____ __ / __/__ ___ _____/ /__ _\ \/ _ \/ _ / __/ _/ /__ / .__/\_,_/_/ /_/\_\ version 3.3.2 /_/ Using Python version 3.9.x Spark context Web UI available at http://localhost:4040 SparkSession available as spark这说明你已经成功进入 PySpark 交互环境了。输入下面代码能跑出结果就说明环境没问题df spark.createDataFrame([(Java, 5), (Python, 10)], [language, score]) df.show()看到下面输出恭喜你的 Spark 环境已经通了------------- |language|score| ------------- | Java| 5| | Python| 10| -------------3.6 第六步完整跑一个 WordCount 任务验证为了验证环境不只是“能打开”而是真正能执行计算任务我习惯跑一个经典的 WordCount。在pyspark交互命令行里执行from pyspark import SparkContext sc SparkContext.getOrCreate() # 随便拿几行文本做测试 lines sc.parallelize([hello world, hello spark, hello windows, spark is powerful]) counts lines.flatMap(lambda line: line.split( )) \ .map(lambda word: (word, 1)) \ .reduceByKey(lambda a, b: a b) \ .collect() for word, count in counts: print(f{word}: {count})如果输出hello: 3 world: 1 spark: 2 windows: 1 is: 1 powerful: 1说明你的 Spark 已经能完成分布式求值了虽然现在是本地模式。这一步跑通后续学 RDD、DataFrame 操作都不会再被环境问题打断。4. 工具选型与场景扩展不止能跑“Hello World”环境搭好只是开始实际用起来还有几个场景值得说清楚。我一开始只会在命令行里用 pyspark后来才发现很多场景要用到 IDE 和 Jupyter。4.1 场景一在 Jupyter Notebook 里用 PySpark很多人学 PySpark 习惯用 Jupyter Notebook因为它交互性好能一步步看结果。配置方式有两种方案一每次启动时指定PYSPARK_DRIVER_PYTHONjupyter PYSPARK_DRIVER_PYTHON_OPTSnotebook pyspark这个命令的意思是用 Jupyter 作为 PySpark 的驱动 Python启动时自动打开 notebook。Windows 的 CMD 下写环境变量比较别扭我给个 PowerShell 版本的写法$env:PYSPARK_DRIVER_PYTHONjupyter $env:PYSPARK_DRIVER_PYTHON_OPTSnotebook pyspark方案二用更优雅的 findspark 库。先 pip 安装pip install findspark然后在 Jupyter 里这样用import findspark findspark.init() from pyspark.sql import SparkSession spark SparkSession.builder.appName(test).getOrCreate()findspark 做的事情就是自动帮你把 Python 指向 Spark 的安装位置省去每次配置环境变量的麻烦。这个方案我用得最多启动稳定而且逻辑清楚。4.2 场景二在 VS Code / PyCharm 里写 PySpark 脚本写正式的项目代码还是得用 IDE。VS Code 里配 PySpark 唯一需要注意的是解释器选择。在 VS Code 里按CtrlShiftP选择 Python 解释器为刚才配好 PySpark 的那个 Python 版本。然后在.py文件顶部用和上面一样的代码就能跑。如果你用的是 PyCharm在 Settings → Project → Python Interpreter 里选择对应的 Python 环境即可其余逻辑一致。注意一个 IDE 里的坑IDE 终端和系统 CMD 的 PATH 可能不一致。如果你在命令行里跑通了但 IDE 里运行时报Java gateway process exited before sending its port number大概率是 IDE 没加载到SPARK_HOME或HADOOP_HOME环境变量。解决方法是重启 IDE或者在 IDE 的终端里重新读取环境变量。4.3 场景三离线环境搭建如果你所在的公司是内网开发环境无法直接访问 PyPI 或 Spark 官网其实也能搭起来。提前准备以下几样东西Spark 的压缩包Windows 版 pre-built 包JDK 8 安装包pyspark 的 whl 文件通过pip download pyspark3.3.2在联网机器上提前下载winutils.exe安装顺序和上面完全一致只是把“下载”这个动作换成 U 盘拷贝。内网环境下唯一可能出问题的是 Python 版本冲突建议用虚拟环境隔离。python -m venv spark_env spark_env\Scripts\activate pip install pyspark-3.3.2-py3-none-any.whl虚拟环境是我在内网环境里比较推荐的做法不污染系统 Python出问题能直接删除重建。5. 常见问题与排查经验我把踩过的坑都给你列出来这部分是我最想分享的内容。环境搭建的“坑”几乎都是报错驱动型的遇到一次就长记性。下面几个问题是我自己和身边朋友反复遇到的按出现频率从高到低排列。5.1 问题一Java gateway process exited before sending its port number这个报错是 PySpark 新手最常见的一道坎百度一搜全是求助帖。常见原因有三个Java 版本不对或JAVA_HOME没配好。先跑java -version确认。SPARK_HOME指向了错误的目录比如没解压完整。PySpark 版本和 Spark 版本不一致。排查顺序建议# 第一步确认 Java 可用 java -version # 第二步确认 Spark 环境变量 echo %SPARK_HOME% echo %JAVA_HOME% # 第三步确认 Python 能看到 pyspark python -c import pyspark; print(pyspark.__version__)确认完以后再重新写一个最小脚本测试。我遇到过一次是 JAVA_HOME 配了 JRE 的路径不是 JDK 的路径报错一模一样换成 JDK 路径就好了。5.2 问题二Could not locate executable null\bin\winutils.exe这个报错非常经典原因就是 HADOOP_HOME 没设置或者 winutils.exe 不在%HADOOP_HOME%\bin目录下。解决办法前面已经写过这里补充一个细节有些版本的 Spark 即使你设置了 HADOOP_HOME 还是报错需要在代码里显式指定import os os.environ[HADOOP_HOME] D:\\bigdata\\hadoop-bin os.environ[SPARK_HOME] D:\\bigdata\\spark-3.3.2-bin-hadoop3然后还需要把%HADOOP_HOME%\bin加入系统 Path。亲测这样操作以后即使 winutils 放的位置比较偏也能找到。如果你不想下载 winutils.exe也有一个“跳过本地库”的办法。在代码里加上spark SparkSession.builder \ .appName(test) \ .config(spark.hadoop.fs.file.impl, org.apache.hadoop.fs.LocalFileSystem) \ .getOrCreate()这个配置的意思是让 Spark 处理本地文件时强制使用 LocalFileSystem绕开对 winutils 的依赖。但是这个方法有个副作用——涉及文件权限检查的功能会变得很弱对本地文件读写可能出错。所以只建议临时测试时用正式环境还是老老实实配 winutils。5.3 问题三PySpark 运行时内存溢出或者任务卡死在 Windows 上跑 Spark默认一个 executor 会尝试使用当前机器的所有内存实际上是 512MB 到 1GB 的默认配置但行为因版本而异。如果你同时开多个程序或者跑 data shuffle 比较大的任务就可能卡死或 OOM。解决办法是启动 SparkSession 时显式配置资源参数spark SparkSession.builder \ .appName(test) \ .master(local[2]) \ .config(spark.driver.memory, 1g) \ .config(spark.executor.memory, 2g) \ .getOrCreate()local[2]表示用两个本地线程跑如果你的电脑是 8 核可以试试local[4]。内存设置多少合适经验法则给系统留至少 2GB 内存剩下的按 2:1 分给 driver 和 executor。比如 16GB 内存的机器可以 driver 4g、executor 8g。但要注意Windows 本身的图形界面、浏览器、IDE 都要吃内存全部塞给 Spark 会导致系统卡死。5.4 问题四Jupyter Notebook 里看不到 Spark 变量这个问题的典型场景是敲pyspark进入交互环境Spark 里面有spark这个默认变量但在 Jupyter 里用SparkSession.builder.getOrCreate()却报错。原因在于 Jupyter 环境没有继承命令行里设置的环境变量。解决办法推荐用 findspark前面已经介绍过这里不再重复。另一个常见问题是 Jupyter 启动后每次都要重复写各种初始化代码。我的做法是提前写好一个spark_init.py文件内容如下import findspark findspark.init() from pyspark.sql import SparkSession def get_spark(app_namePySparkApp): return SparkSession.builder \ .appName(app_name) \ .master(local[*]) \ .config(spark.driver.memory, 2g) \ .getOrCreate()以后新建 notebook第一行from spark_init import get_spark第二行spark get_spark()就能直接用省事很多。这个小文件我保存了很长时间换电脑搭环境时直接复制过去就能用。5.5 问题五不是坑的“垃圾日志刷屏”启动 PySpark 时满屏的 INFO 日志把真正的输出都淹没了。这个问题非常好解决找到%SPARK_HOME%\conf目录把log4j2.properties.template复制一份重命名为log4j2.properties然后打开文件把根日志级别从 INFO 改成 WARNrootLogger.level WARN再重启 pyspark世界清净了。注意 Spark 3.3 之后用的是 log4j2不是以前那个log4j.properties网上很多老教程还停留在旧版本跟着改会找不到文件。还有一个小技巧如果你不想改全局配置只关心某个自定义日志的输出可以在 Python 代码里用标准 logging 库把 pyspark 的日志级别降到 ERRORimport logging logging.getLogger(py4j).setLevel(logging.ERROR)5.6 问题六版本不对导致的“隐藏坑”最后说一个最隐蔽的坑。有一次我两台电脑一起搭A 电脑用 Spark 3.3.2 Python 3.9一切正常B 电脑用 Spark 3.5.0 Python 3.12PySpark 能导入但一执行collect()就报 Python 进程退出的诡异错误报错信息完全没参考价值。后来查了 GitHub issue 才发现Spark 3.5.x 的某些版本对 Python 3.12 的兼容性有 bug官方在 3.5.1 之后才修复。这就是最典型的“版本组合问题”——单独看每个组件都没问题组合起来就翻车。所以如果你遇到网上搜不到解决方案的玄学报错优先怀疑版本组合直接换成我给出的稳定组合Java 8 Spark 3.3.x Python 3.9大概率能解决。6. 环境验证清单确保你真的“搭好了”最后给你一个自查清单建议照着顺序检查一遍Java 环境java -version能看到版本号echo %JAVA_HOME%指向 JDK 路径。Spark 命令pyspark能进入交互环境spark变量可用。PySpark 包pip show pyspark显示正确版本。winutils 补丁%HADOOP_HOME%\bin\winutils.exe存在。WordCount 测试前面 3.6 小节的测试代码能跑通。IDE 运行通过脚本文件非命令行能正常执行 PySpark 任务。这六项全部通过Windows 上的 Python Spark 环境就算真正搭好了。之后可以放心学 DataFrame、Spark SQL、MLlib不会被环境问题反复打断。说句心里话Windows 上搭 Spark 确实是件“功夫活”但一旦跑通一遍你对 Spark 的进程模型、环境变量机制、JVM 与 Python 的交互原理都会有更深的理解这个过程本身就是一次很好的学习。我后来去配 Linux 服务器上的 Spark很多东西都是一通百通的。如果你照着这篇文章操作还是卡在某一步大概率是版本细节没对齐。回到第二部分的版本对照表逐项检查把不一致的地方调整过来基本都能解决。环境搭好以后建议趁热打铁把 Spark 的 DataFrame 操作和 SQL 查询都跑一遍这批基础能力才是后面干活的主力。