第一次接触PySpark时,我被它强大的分布式计算能力吸引,但环境配置过程却让我踩了不少坑。记得有次因为Python版本问题调试到凌晨两点,现在回想起来,那些问题其实都有很简单的解决方案。本文将带你避开这些"坑",用最直接的方式完成PySpark环境搭建。
PySpark是Apache Spark的Python API,它让你能用Python代码调用Spark的分布式计算引擎。相比Java/Scala版本,PySpark更适合数据分析和机器学习场景。我推荐使用Python 3.7+和Spark 3.x的组合,这是目前最稳定的搭配。下面就以Ubuntu 20.04系统为例,带你一步步搭建环境。
很多Linux系统默认安装的是Python 2,但PySpark现在已全面支持Python 3。我建议使用pyenv来管理多版本Python,这样不会影响系统自带的Python环境:
bash复制# 安装依赖
sudo apt-get update
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev
# 安装pyenv
curl https://pyenv.run | bash
echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
source ~/.bashrc
# 安装Python 3.8
pyenv install 3.8.12
pyenv global 3.8.12
验证安装是否成功:
bash复制python --version
# 应该输出 Python 3.8.12
Spark运行需要Java环境,推荐安装OpenJDK 8或11:
bash复制sudo apt-get install -y openjdk-11-jdk
java -version
# 应该显示类似 openjdk version "11.0.11"
如果系统已有其他Java版本,可以通过以下命令切换:
bash复制sudo update-alternatives --config java
我建议直接从官网下载预编译版本,省去编译时间。目前Spark 3.2.1是较稳定的版本:
bash复制wget https://archive.apache.org/dist/spark/spark-3.2.1/spark-3.2.1-bin-hadoop3.2.tgz
tar -xzf spark-3.2.1-bin-hadoop3.2.tgz
sudo mv spark-3.2.1-bin-hadoop3.2 /usr/local/spark
设置环境变量,编辑~/.bashrc文件:
bash复制echo 'export SPARK_HOME=/usr/local/spark' >> ~/.bashrc
echo 'export PATH=$PATH:$SPARK_HOME/bin' >> ~/.bashrc
echo 'export PYSPARK_PYTHON=python' >> ~/.bashrc
echo 'export PYTHONPATH=$SPARK_HOME/python:$PYTHONPATH' >> ~/.bashrc
source ~/.bashrc
运行pyspark交互式环境测试:
bash复制pyspark
如果看到Spark欢迎界面和Python版本信息,说明基础环境已配置成功。第一次启动可能会稍慢,因为Spark需要初始化环境。
这是新手最常见的问题,错误提示通常是"No module named py4j"。解决方法:
例如,如果你看到py4j-0.10.9.2-src.zip,那么应该这样设置:
bash复制echo 'export PYTHONPATH=$SPARK_HOME/python:$SPARK_HOME/python/lib/py4j-0.10.9.2-src.zip:$PYTHONPATH' >> ~/.bashrc
source ~/.bashrc
如果遇到Java版本不兼容的问题,可以明确指定Java路径:
bash复制echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc
source ~/.bashrc
让我们用PySpark实现一个经典的单词统计程序。首先创建测试文件:
bash复制mkdir -p /usr/local/spark/mycode/python
echo "hello world\nhello spark\nspark is awesome" > /usr/local/spark/mycode/python/test.txt
然后创建Python脚本wordcount.py:
python复制from pyspark.sql import SparkSession
# 创建SparkSession
spark = SparkSession.builder \
.appName("WordCount") \
.getOrCreate()
# 读取文本文件
lines = spark.read.text("/usr/local/spark/mycode/python/test.txt").rdd \
.map(lambda x: x[0])
# 单词统计
counts = lines.flatMap(lambda line: line.split(" ")) \
.map(lambda word: (word, 1)) \
.reduceByKey(lambda a, b: a + b)
# 输出结果
output = counts.collect()
for (word, count) in output:
print("%s: %i" % (word, count))
# 停止SparkSession
spark.stop()
提交作业运行:
bash复制spark-submit /usr/local/spark/mycode/python/wordcount.py
下面我们处理一个更复杂的数据集,计算成绩数据的统计指标。先准备数据文件grades.csv:
code复制name,math,english,science
Alice,85,90,88
Bob,78,85,92
Charlie,92,88,95
David,80,82,78
Eve,95,91,94
创建analysis.py脚本:
python复制from pyspark.sql import SparkSession
from pyspark.sql.functions import avg, max, min
spark = SparkSession.builder \
.appName("GradeAnalysis") \
.getOrCreate()
# 读取CSV文件
df = spark.read.csv("/usr/local/spark/mycode/python/grades.csv",
header=True,
inferSchema=True)
# 计算各科平均分
avg_grades = df.select(
avg("math").alias("avg_math"),
avg("english").alias("avg_english"),
avg("science").alias("avg_science")
).collect()[0]
print(f"数学平均分: {avg_grades['avg_math']:.2f}")
print(f"英语平均分: {avg_grades['avg_english']:.2f}")
print(f"科学平均分: {avg_grades['avg_science']:.2f}")
# 找出数学最高分的学生
top_math = df.orderBy(df.math.desc()).first()
print(f"\n数学最高分: {top_math['name']} {top_math['math']}分")
spark.stop()
运行这个脚本,你将看到各科平均分和数学最高分的学生信息。通过这两个例子,你应该已经掌握了PySpark的基本使用方法。在实际项目中,你可以处理TB级别的数据,而代码结构基本保持不变,这就是Spark的强大之处。