📘 PySpark 数据输出终极指南:如何在 Windows 成功使用 saveAsTextFile() 全流程教程
本文目标
你是否遇到过如下报错?
bash
java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z
Caused by: java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z
由于找不到 MSVCR120.dll,无法继续执行代码。
今天,我们将彻底解决这个问题 ,并让你:
成功运行rdd.saveAsTextFile("D:/output1")
在 Windows 环境中使用 Spark 原生输出方式
构建生产级 PySpark 流程(数据输入 → 计算 → 输出)
一、为什么 saveAsTextFile() 会崩溃?
根本原因(深度解析):
MSVCR120.dll 是 Microsoft Visual C++ 2013 Redistributable Runtime 的一部分。
当你执行:
python
rdd.saveAsTextFile("D:/output1")
Spark 会尝试使用 Hadoop 的 原生本地库(native IO) 来写文件,其依赖如下链:
Spark → Hadoop → nativeio.dll → NativeIO$Windows.access0() → MSVCR120.dll
当系统找不到 MSVCR120.dll,就会抛出 UnsatisfiedLinkError。
即使你不用
saveAsTextFile(),只要在PATH中加入了E:\APP\hadoop-3.4.2\bin,Spark 仍会尝试加载 native IO!
二、解决方案:三步闭环法(配置 + 权限 + 修复)
最终目标:让你的
rdd.saveAsTextFile("D:/output1")成功运行
第一步:配置 PATH + PYSPARK_PYTHON
python
import os
# 1. 指定 Python 解释器路径(必须!)
os.environ["PYSPARK_PYTHON"] = "D:\\APP\\Anaconda\\envs\\spark_env\\python.exe"
# 2. 设置超时,防止 task 中断
os.environ['PYSPARK_TIMEOUT'] = '600'
os.environ['PYSPARK_DRIVER_TIMEOUT'] = '600'
# 3. 关键:添加 Hadoop bin 到 PATH
os.environ['PATH'] += os.pathsep + 'E:\\APP\\hadoop-3.4.2\\bin'
# 4. 推荐:设置 Driver Python 解释器
os.environ["PYSPARK_DRIVER_PYTHON"] = "D:\\APP\\Anaconda\\envs\\spark_env\\python.exe"
注意 :
os.pathsep是 路径分隔符 ,Windows 下应为;,不是/。
第二步:放置 winutils.exe 并修复权限
📌 前提 :你已经下载了
winutils.exe(Hadoop 官方二进制,支持 Windows)
下载地址(请使用匹配版本):
https://github.com/cdarlint/winutils
建议使用版本:hadoop-3.4.2
步骤 1:将 winutils.exe 、hadoop.dll 放入 E:\APP\hadoop-3.4.2\bin 目录 和 c盘 C:\Windows\System32 里面
E:\APP\hadoop-3.4.2\bin\winutils.exe
步骤 2:以管理员身份打开 CMD
右键 "命令提示符" → "以管理员身份运行"
步骤 3:执行权限修复命令
bash
winutils.exe chmod 777 C:\tmp\Hive
💡 说明:
C:\tmp\Hive是 Hadoop 临时目录,用于存储临时文件chmod 777给所有用户读写执行权限- 此步骤会修复 Hadoop 文件系统权限问题
成功提示:无报错,返回正常。
可选:你还可以用第三方工具如"联想电脑管家"修复系统 DLL 问题。
第三步:验证是否成功运行
python
from pyspark import SparkConf, SparkContext
# 配置环境(确保与上一致)
os.environ["PYSPARK_PYTHON"] = "D:\\APP\\Anaconda\\envs\\spark_env\\python.exe"
os.environ['PYSPARK_TIMEOUT'] = '600'
os.environ['PYSPARK_DRIVER_TIMEOUT'] = '600'
os.environ['PATH'] += os.pathsep + 'E:\\APP\\hadoop-3.4.2\\bin'
# 创建 SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("test_saveAsTextFile")
sc = SparkContext(conf=conf)
# 创建 RDD
rdd = sc.parallelize([1, 2, 3, 4, 5])
# 成功输出!
rdd.saveAsTextFile("D:/output1")
print(" 数据已成功输出到 D:/output1")
# 停止
sc.stop()
运行结果:
- 生成文件夹
D:/output1- 包含
_SUCCESS和part-00000文件- 没有
MSVCR120.dll报错
三、为什么推荐 saveAsTextFile()?
| 方案 | 优点 | 缺点 |
|---|---|---|
collect() + open() |
避开 native IO,稳定 | 不能用于集群、本地写但不是标准输出 |
saveAsTextFile() |
标准、兼容生产、支持分布式文件系统 | 依赖 native IO(但可修复) |
推荐理由:
- 是 Spark 官方输出方式
- 可用于 HDFS、S3、SFTP 等生产环境
- 项目提交、团队协作、CI/CD 时更具规范性
四、完整三步模型:数据输入 → 计算 → 输出
python
# 1. 【数据输入】
from pyspark import SparkConf, SparkContext
import os
os.environ["PYSPARK_PYTHON"] = "D:\\APP\\Anaconda\\envs\\spark_env\\python.exe"
os.environ['PYSPARK_TIMEOUT'] = '600'
os.environ['PYSPARK_DRIVER_TIMEOUT'] = '600'
os.environ['PATH'] += os.pathsep + 'E:\\APP\\hadoop-3.4.2\\bin'
conf = SparkConf().setMaster("local[*]").setAppName("sales_analysis")
sc = SparkContext(conf=conf)
rdd = sc.parallelize([1, 2, 3, 4, 5])
# 2. 【数据计算】
rdd2 = rdd.map(lambda x: x * 2)
rdd3 = rdd2.filter(lambda x: x > 3)
# 3. 【数据输出】 原生输出方式
rdd3.saveAsTextFile("D:/output_final")
print(" 三步流程完成:输入 → 计算 → 输出")
sc.stop()
本代码可直接运行,无需
collect(),无需open(),是标准 PySpark 工作流。
五、总结:成功运行 saveAsTextFile() 的 5 个关键点
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1️⃣ | winutils.exe 放入 hadoop/bin |
缺少则无法访问本地 FS |
| 2️⃣ | 以管理员身份运行 CMD | 执行 chmod 才能生效 |
| 3️⃣ | chmod 777 C:\tmp\Hive |
修复权限,避免写入失败 |
| 4️⃣ | PATH 包含 hadoop/bin |
启用 native IO |
| 5️⃣ | PYSPARK_TIMEOUT=600 |
防止任务因超时中断 |
附录:完整环境配置模板(可复制)
python
import os
# 1. 设置 Python
os.environ["PYSPARK_PYTHON"] = "D:\\APP\\Anaconda\\envs\\spark_env\\python.exe"
os.environ["PYSPARK_DRIVER_PYTHON"] = "D:\\APP\\Anaconda\\envs\\spark_env\\python.exe"
# 2. 超时设置
os.environ['PYSPARK_TIMEOUT'] = '600'
os.environ['PYSPARK_DRIVER_TIMEOUT'] = '600'
# 3. 加载 Hadoop native 库
os.environ['PATH'] += os.pathsep + 'E:\\APP\\hadoop-3.4.2\\bin'
# 4. 创建 SparkContext
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("my_app")
sc = SparkContext(conf=conf)
# 测试
rdd = sc.parallelize([1,2,3])
rdd.saveAsTextFile("D:/test_output")
print(" 成功写入")
sc.stop()