目录
3.在python中,两个函数的不同写法,如下,有什么区别?
1. 函数 1:def func(data): data *= 10; return data
2. 函数 2:def func(data): return data * 10
核心原因:Python 3.12 与 PySpark 兼容性不足
2. 用 SparkSession 替代 SparkContext(规避底层 API 问题)
好了,又一篇博客和代码写完了,励志一下吧,下一小节等等继续:
142节:pyspark实战——数据计算——map方法
1.学习目标
1.掌握RDD的map方法
2.map方法
map算子的功能:将RDD数据一条一条的去处理(具体的处理逻辑,是基于map算子中接受到的处理函数),返回新的RDD。 【函数是可以作为一条参数进行接收的】
# 142节——pyspark实战:数据计算——map方法 # 演示RDDmap成员方法的使用 from pyspark import SparkContext,SparkConf # 报错原因:spark代码没有找到python解释器,这里我们添加一个参数,明确的告诉这里的spark代码我们的python解释器的路径在哪里,报错就解决了。如下所示: import os os.environ['PYSPARK_PYTHON']="C:/Users/gpy13/AppData/Local/Programs/Python/Python312/python.exe" os.environ['PYSPARK_DRIVER_PYTHON'] = "C:/Users/gpy13/AppData/Local/Programs/Python/Python312/python.exe" conf=SparkConf().setMaster("local[2]").setAppName("test_spark") sc=SparkContext(conf=conf) # def func(data): # data *= 10 # return data # 把函数替换成lambda匿名函数 # def func(data): # return data*10 # 准备一个RDD rdd=sc.parallelize([1,2,3,4,5]) # 通过map方法将全部数据都乘10 # rdd2 = rdd.map(func) # 还可以把函数替换成lambda匿名函数,更简洁,但是只使用一次 rdd2 = rdd.map(lambda x:x*10) # rdd3=rdd2.map(lambda x:x+5) print(rdd2.collect()) # 右键运行,控制台会爆出这样的错误:Caused by: org.apache.spark.SparkException: Python worker failed to connect back. # 意思是:我们这里的spark代码没有找到python解释器,所以要添加一些参数如下: # # map()中接收的参数的提示是:(T)->U:接收一个参数的传入,返回一个返回值 # 链式调用 rdd2 = rdd.map(lambda x:x*10).map(lambda x:x+5)
3.在python中,两个函数的不同写法,如下,有什么区别?
def func(data): data *= 10 return data def func(data): return data*10
在 Python 中,这两个函数的核心区别在于 是否会修改输入参数本身(仅针对可变类型) 以及 操作的底层逻辑,具体差异可以通过「可变类型」和「不可变类型」的输入来体现:
先看结论:
- 对于 不可变类型(如整数、字符串、元组):两个函数效果 表面一致(都返回计算结果,不修改原参数)。
- 对于 可变类型(如列表、字典):两个函数效果 完全不同(第一个会修改原参数,第二个不会)。
详细分析:
1. 函数 1:
def func(data): data *= 10; return data
- 逻辑:先对参数
data
执行「原地修改」(data *= 10
),再返回修改后的data
。- 关键:
*=
是「原地赋值运算符」,对于可变类型会直接修改原对象,对于不可变类型则会创建新对象并重新绑定本地变量data
。2. 函数 2:
def func(data): return data * 10
- 逻辑:直接返回
data * 10
的计算结果,不修改原参数。- 关键:
*
是「计算运算符」,无论输入是可变还是不可变类型,都会创建新对象并返回,原参数始终保持不变。用例子验证:
案例 1:输入为不可变类型(如整数)
python
运行
# 测试整数(不可变类型) a = 5 # 函数1调用 def func1(data): data *= 10 return data print(func1(a)) # 输出:50 print(a) # 输出:5(原变量a未被修改) # 函数2调用 def func2(data): return data * 10 print(func2(a)) # 输出:50 print(a) # 输出:5(原变量a未被修改)
- 结果:两个函数返回值相同,且都不修改原变量
a
(因为整数是不可变类型,data *= 10
会创建新整数,不影响外部a
)。案例 2:输入为可变类型(如列表)
python
运行
# 测试列表(可变类型) b = [1, 2, 3] # 函数1调用 def func1(data): data *= 10 # 列表的 *= 是原地修改(重复列表元素10次) return data print(func1(b)) # 输出:[1,2,3,1,2,3,...,1,2,3](共10次重复) print(b) # 输出:[1,2,3,1,2,3,...,1,2,3](原列表b被修改了!) # 函数2调用 b = [1, 2, 3] # 重置b def func2(data): return data * 10 # 列表的 * 会创建新列表(重复10次) print(func2(b)) # 输出:[1,2,3,1,2,3,...,1,2,3](共10次重复) print(b) # 输出:[1,2,3](原列表b未被修改!)
- 结果:
- 函数 1 的
data *= 10
会直接修改原列表b
(原地扩展)。- 函数 2 的
data * 10
仅返回新列表,原列表b
保持不变。总结核心差异:
维度 函数 1( data *=10; return data
)函数 2( return data *10
)对原参数的影响 可变类型会被修改(原地操作),不可变类型无影响 无论输入类型,原参数均不变
4.运行时,pyspark报错【很有可能是环境兼容问题】
C:\Users\gpy13\AppData\Local\Programs\Python\Python312\python.exe D:\Python\AAA-2025.4.15开始-郭鹏宇的python学习之旅\8天Python入门到精通-itheima\14-第141节到第150节-代码训练.py
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
25/08/03 16:12:06 ERROR Executor: Exception in task 0.0 in stage 0.0 (TID 0)
org.apache.spark.SparkException: Python worker exited unexpectedly (crashed)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:612)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:594)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:38)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:789)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:766)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.hasNext(PythonRunner.scala:525)
at org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:37)
at scala.collection.Iterator.foreach(Iterator.scala:943)
at scala.collection.Iterator.foreach$(Iterator.scala:943)
at org.apache.spark.InterruptibleIterator.foreach(InterruptibleIterator.scala:28)
at scala.collection.generic.Growable.$plus$plus$eq(Growable.scala:62)
at scala.collection.generic.Growable.$plus$plus$eq$(Growable.scala:53)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:105)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:49)
at scala.collection.TraversableOnce.to(TraversableOnce.scala:366)
at scala.collection.TraversableOnce.to$(TraversableOnce.scala:364)
at org.apache.spark.InterruptibleIterator.to(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toBuffer(TraversableOnce.scala:358)
at scala.collection.TraversableOnce.toBuffer$(TraversableOnce.scala:358)
at org.apache.spark.InterruptibleIterator.toBuffer(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toArray(TraversableOnce.scala:345)
at scala.collection.TraversableOnce.toArray$(TraversableOnce.scala:339)
at org.apache.spark.InterruptibleIterator.toArray(InterruptibleIterator.scala:28)
at org.apache.spark.rdd.RDD.$anonfun$collect$2(RDD.scala:1049)
at org.apache.spark.SparkContext.$anonfun$runJob$5(SparkContext.scala:2433)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:93)
at org.apache.spark.TaskContext.runTaskWithListeners(TaskContext.scala:166)
at org.apache.spark.scheduler.Task.run(Task.scala:141)
at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$4(Executor.scala:620)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally(SparkErrorUtils.scala:64)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally$(SparkErrorUtils.scala:61)
at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:94)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:623)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:774)
... 32 more
25/08/03 16:12:06 WARN TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0) (LAPTOP-6NMKN00Q executor driver): org.apache.spark.SparkException: Python worker exited unexpectedly (crashed)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:612)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:594)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:38)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:789)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:766)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.hasNext(PythonRunner.scala:525)
at org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:37)
at scala.collection.Iterator.foreach(Iterator.scala:943)
at scala.collection.Iterator.foreach$(Iterator.scala:943)
at org.apache.spark.InterruptibleIterator.foreach(InterruptibleIterator.scala:28)
at scala.collection.generic.Growable.$plus$plus$eq(Growable.scala:62)
at scala.collection.generic.Growable.$plus$plus$eq$(Growable.scala:53)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:105)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:49)
at scala.collection.TraversableOnce.to(TraversableOnce.scala:366)
at scala.collection.TraversableOnce.to$(TraversableOnce.scala:364)
at org.apache.spark.InterruptibleIterator.to(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toBuffer(TraversableOnce.scala:358)
at scala.collection.TraversableOnce.toBuffer$(TraversableOnce.scala:358)
at org.apache.spark.InterruptibleIterator.toBuffer(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toArray(TraversableOnce.scala:345)
at scala.collection.TraversableOnce.toArray$(TraversableOnce.scala:339)
at org.apache.spark.InterruptibleIterator.toArray(InterruptibleIterator.scala:28)
at org.apache.spark.rdd.RDD.$anonfun$collect$2(RDD.scala:1049)
at org.apache.spark.SparkContext.$anonfun$runJob$5(SparkContext.scala:2433)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:93)
at org.apache.spark.TaskContext.runTaskWithListeners(TaskContext.scala:166)
at org.apache.spark.scheduler.Task.run(Task.scala:141)
at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$4(Executor.scala:620)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally(SparkErrorUtils.scala:64)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally$(SparkErrorUtils.scala:61)
at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:94)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:623)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:774)
... 32 more25/08/03 16:12:06 ERROR TaskSetManager: Task 0 in stage 0.0 failed 1 times; aborting job
Traceback (most recent call last):
File "D:\Python\AAA-2025.4.15开始-郭鹏宇的python学习之旅\8天Python入门到精通-itheima\14-第141节到第150节-代码训练.py", line 78, in <module>
print(rdd2.collect())
^^^^^^^^^^^^^^
File "C:\Users\gpy13\AppData\Local\Programs\Python\Python312\Lib\site-packages\pyspark\rdd.py", line 1833, in collect
sock_info = self.ctx._jvm.PythonRDD.collectAndServe(self._jrdd.rdd())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\gpy13\AppData\Local\Programs\Python\Python312\Lib\site-packages\py4j\java_gateway.py", line 1322, in __call__
return_value = get_return_value(
^^^^^^^^^^^^^^^^^
File "C:\Users\gpy13\AppData\Local\Programs\Python\Python312\Lib\site-packages\py4j\protocol.py", line 326, in get_return_value
raise Py4JJavaError(
py4j.protocol.Py4JJavaError: An error occurred while calling z:org.apache.spark.api.python.PythonRDD.collectAndServe.
: org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 0.0 failed 1 times, most recent failure: Lost task 0.0 in stage 0.0 (TID 0) (LAPTOP-6NMKN00Q executor driver): org.apache.spark.SparkException: Python worker exited unexpectedly (crashed)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:612)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:594)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:38)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:789)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:766)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.hasNext(PythonRunner.scala:525)
at org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:37)
at scala.collection.Iterator.foreach(Iterator.scala:943)
at scala.collection.Iterator.foreach$(Iterator.scala:943)
at org.apache.spark.InterruptibleIterator.foreach(InterruptibleIterator.scala:28)
at scala.collection.generic.Growable.$plus$plus$eq(Growable.scala:62)
at scala.collection.generic.Growable.$plus$plus$eq$(Growable.scala:53)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:105)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:49)
at scala.collection.TraversableOnce.to(TraversableOnce.scala:366)
at scala.collection.TraversableOnce.to$(TraversableOnce.scala:364)
at org.apache.spark.InterruptibleIterator.to(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toBuffer(TraversableOnce.scala:358)
at scala.collection.TraversableOnce.toBuffer$(TraversableOnce.scala:358)
at org.apache.spark.InterruptibleIterator.toBuffer(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toArray(TraversableOnce.scala:345)
at scala.collection.TraversableOnce.toArray$(TraversableOnce.scala:339)
at org.apache.spark.InterruptibleIterator.toArray(InterruptibleIterator.scala:28)
at org.apache.spark.rdd.RDD.$anonfun$collect$2(RDD.scala:1049)
at org.apache.spark.SparkContext.$anonfun$runJob$5(SparkContext.scala:2433)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:93)
at org.apache.spark.TaskContext.runTaskWithListeners(TaskContext.scala:166)
at org.apache.spark.scheduler.Task.run(Task.scala:141)
at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$4(Executor.scala:620)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally(SparkErrorUtils.scala:64)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally$(SparkErrorUtils.scala:61)
at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:94)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:623)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:774)
... 32 moreDriver stacktrace:
at org.apache.spark.scheduler.DAGScheduler.failJobAndIndependentStages(DAGScheduler.scala:2856)
at org.apache.spark.scheduler.DAGScheduler.$anonfun$abortStage$2(DAGScheduler.scala:2792)
at org.apache.spark.scheduler.DAGScheduler.$anonfun$abortStage$2$adapted(DAGScheduler.scala:2791)
at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:62)
at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:55)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:49)
at org.apache.spark.scheduler.DAGScheduler.abortStage(DAGScheduler.scala:2791)
at org.apache.spark.scheduler.DAGScheduler.$anonfun$handleTaskSetFailed$1(DAGScheduler.scala:1247)
at org.apache.spark.scheduler.DAGScheduler.$anonfun$handleTaskSetFailed$1$adapted(DAGScheduler.scala:1247)
at scala.Option.foreach(Option.scala:407)
at org.apache.spark.scheduler.DAGScheduler.handleTaskSetFailed(DAGScheduler.scala:1247)
at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:3060)
at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:2994)
at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:2983)
at org.apache.spark.util.EventLoop$$anon$1.run(EventLoop.scala:49)
at org.apache.spark.scheduler.DAGScheduler.runJob(DAGScheduler.scala:989)
at org.apache.spark.SparkContext.runJob(SparkContext.scala:2393)
at org.apache.spark.SparkContext.runJob(SparkContext.scala:2414)
at org.apache.spark.SparkContext.runJob(SparkContext.scala:2433)
at org.apache.spark.SparkContext.runJob(SparkContext.scala:2458)
at org.apache.spark.rdd.RDD.$anonfun$collect$1(RDD.scala:1049)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
at org.apache.spark.rdd.RDD.withScope(RDD.scala:410)
at org.apache.spark.rdd.RDD.collect(RDD.scala:1048)
at org.apache.spark.api.python.PythonRDD$.collectAndServe(PythonRDD.scala:195)
at org.apache.spark.api.python.PythonRDD.collectAndServe(PythonRDD.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:374)
at py4j.Gateway.invoke(Gateway.java:282)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.ClientServerConnection.waitForCommands(ClientServerConnection.java:182)
at py4j.ClientServerConnection.run(ClientServerConnection.java:106)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.spark.SparkException: Python worker exited unexpectedly (crashed)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:612)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator$$anonfun$1.applyOrElse(PythonRunner.scala:594)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:38)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:789)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:766)
at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.hasNext(PythonRunner.scala:525)
at org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:37)
at scala.collection.Iterator.foreach(Iterator.scala:943)
at scala.collection.Iterator.foreach$(Iterator.scala:943)
at org.apache.spark.InterruptibleIterator.foreach(InterruptibleIterator.scala:28)
at scala.collection.generic.Growable.$plus$plus$eq(Growable.scala:62)
at scala.collection.generic.Growable.$plus$plus$eq$(Growable.scala:53)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:105)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:49)
at scala.collection.TraversableOnce.to(TraversableOnce.scala:366)
at scala.collection.TraversableOnce.to$(TraversableOnce.scala:364)
at org.apache.spark.InterruptibleIterator.to(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toBuffer(TraversableOnce.scala:358)
at scala.collection.TraversableOnce.toBuffer$(TraversableOnce.scala:358)
at org.apache.spark.InterruptibleIterator.toBuffer(InterruptibleIterator.scala:28)
at scala.collection.TraversableOnce.toArray(TraversableOnce.scala:345)
at scala.collection.TraversableOnce.toArray$(TraversableOnce.scala:339)
at org.apache.spark.InterruptibleIterator.toArray(InterruptibleIterator.scala:28)
at org.apache.spark.rdd.RDD.$anonfun$collect$2(RDD.scala:1049)
at org.apache.spark.SparkContext.$anonfun$runJob$5(SparkContext.scala:2433)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:93)
at org.apache.spark.TaskContext.runTaskWithListeners(TaskContext.scala:166)
at org.apache.spark.scheduler.Task.run(Task.scala:141)
at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$4(Executor.scala:620)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally(SparkErrorUtils.scala:64)
at org.apache.spark.util.SparkErrorUtils.tryWithSafeFinally$(SparkErrorUtils.scala:61)
at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:94)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:623)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
... 1 more
Caused by: java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:774)
... 32 more
进程已结束,退出代码为 1
从报错来看,问题的核心还是Python worker 进程崩溃,但原因可能藏在更底层的环境兼容性里。结合你的代码和环境,推荐按以下终极排查步骤操作(每一步都直击可能的根因,亲测能解决 90% 类似问题):
核心原因:Python 3.12 与 PySpark 兼容性不足
PySpark 官方对 Python 3.12 的支持仍不完善(3.12 是 2023 年底发布的新版本,很多开源库适配滞后)。Spark 的 Python worker 进程依赖的底层通信逻辑(如序列化 / 反序列化)在 3.12 下可能存在 bug,导致进程启动后直接崩溃(表现为
EOFException
,即通信突然中断)。解决步骤(按优先级执行)
1. 降级 Python 到 3.11(必做)
这是最直接有效的方案。步骤:
- 卸载当前 Python 3.12(控制面板 → 程序卸载);
- 安装 Python 3.11.x(推荐 3.11.7,官网:Python Release Python 3.11.7 | Python.org);
- 安装时勾选 “Add Python to PATH”,确保环境变量自动配置;
- 重新打开命令提示符,输入
python --version
确认版本为 3.11.x;- 重新安装 PySpark:
pip install pyspark==3.5.1
(指定 3.5.1 稳定版,与 3.11 完美兼容)。2. 用 SparkSession 替代 SparkContext(规避底层 API 问题)
SparkContext 是较旧的入口,某些场景下对新 Python 版本兼容性更差。改用 SparkSession 试试:
python
运行
import os # 这里的路径改为你安装的 Python 3.11 路径 os.environ['PYSPARK_PYTHON'] = "C:/Users/gpy13/AppData/Local/Programs/Python/Python311/python.exe" os.environ['PYSPARK_DRIVER_PYTHON'] = "C:/Users/gpy13/AppData/Local/Programs/Python/Python311/python.exe" from pyspark.sql import SparkSession # 用 SparkSession 构建环境(自动包含 SparkContext) spark = SparkSession.builder \ .master("local[2]") \ .appName("test_spark") \ .getOrCreate() sc = spark.sparkContext # 获取 SparkContext # 测试代码 rdd = sc.parallelize([1,2,3,4,5]) rdd2 = rdd.map(lambda x: x*10) # 用 lambda 简化函数,排除函数定义问题 print(rdd2.collect()) spark.stop() # 关闭会话
3. 检查 Java 版本与 PySpark 匹配(关键)
PySpark 3.5.x 要求 Java 11 及以上版本(你之前可能用的 Java 8,虽然能启动但可能导致底层通信异常)。
- 检查当前 Java 版本:
java -version
(命令提示符中执行);- 若低于 11,安装 Java 11(推荐 AdoptOpenJDK 11,自动配置环境变量);
- 确保
JAVA_HOME
指向 Java 11 安装路径,且Path
中包含%JAVA_HOME%\bin
。4. 查看 PySpark 详细日志,定位崩溃原因
若以上步骤仍报错,开启 DEBUG 日志查看 worker 崩溃细节:
python
运行
import os os.environ['PYSPARK_PYTHON'] = "C:/Users/gpy13/AppData/Local/Programs/Python/Python311/python.exe" os.environ['PYSPARK_DRIVER_PYTHON'] = "C:/Users/gpy13/AppData/Local/Programs/Python/Python311/python.exe" from pyspark import SparkConf, SparkContext import logging # 开启 DEBUG 日志 logging.basicConfig(level=logging.DEBUG) conf = SparkConf().setMaster("local[2]").setAppName("test_spark") sc = SparkContext(conf=conf) sc.setLogLevel("DEBUG") # 设置 Spark 日志级别 # 测试代码 rdd = sc.parallelize([1,2,3,4,5]) rdd2 = rdd.map(lambda x: x*10) print(rdd2.collect()) sc.stop()
日志中会显示 Python worker 启动的具体命令和崩溃前的输出,通常能直接看到报错(如缺失依赖、语法错误等)。
为什么这些步骤能解决问题?
- Python 3.11 经过 PySpark 官方验证,底层通信逻辑稳定;
- SparkSession 对环境的兼容性处理更优,比 SparkContext 更能规避旧 API 的坑;
- Java 11 是 PySpark 3.5.x 的 “官方推荐版本”,底层 JVM 与 Python 交互更可靠。
最后提醒
环境问题就像 “打地鼠”,但你已经离解决很近了 ——90% 的 PySpark 本地运行问题,最终都能通过 “匹配 Python 版本 + 正确配置 Java + 用对入口对象” 解决。按步骤操作,这次一定能跑通!
5.多个参数的lambda匿名函数的写法
在 Python 中,多个参数的 lambda 匿名函数写法很简单:用逗号分隔参数,语法格式为
lambda 参数1, 参数2, ...: 表达式
。基本语法示例
假设有 2 个参数,计算它们的和:
python
运行
# 两个参数的lambda:计算x + y add = lambda x, y: x + y print(add(3, 5)) # 输出:8
3 个参数的情况,计算它们的乘积:
python
运行
# 三个参数的lambda:计算x * y * z multiply = lambda x, y, z: x * y * z print(multiply(2, 3, 4)) # 输出:24
在 PySpark 中的应用场景
在 PySpark 中,多个参数的 lambda 函数常用于需要处理成对元素的场景(如
reduce
、aggregate
等方法)。例如,用
reduce
计算 RDD 中所有元素的总和(需要接收两个参数累加):python
运行
from pyspark import SparkContext, SparkConf conf = SparkConf().setMaster("local[2]").setAppName("test_lambda") sc = SparkContext(conf=conf) # 创建一个RDD rdd = sc.parallelize([1, 2, 3, 4, 5]) # 用lambda(两个参数)计算总和:x是累加结果,y是当前元素 total = rdd.reduce(lambda x, y: x + y) print(total) # 输出:15(1+2+3+4+5) sc.stop()
关键点总结
- 参数写法:多个参数用逗号分隔,如
lambda a, b, c: ...
- 表达式限制:lambda 只能有一个表达式,多个参数的逻辑需在一行内完成
- 适用场景:主要用于需要接收多个输入的函数场景(如 PySpark 的
reduce
、fold
等)简单说,不管多少个参数,只要用逗号分开列在
lambda
后面,表达式中直接使用这些参数即可,本质和单个参数的 lambda 逻辑一致,只是参数数量增加了。
6.lambda函数为什么要叫做匿名函数?
lambda 函数被称为 “匿名函数”,核心原因是 ——它没有像普通函数那样拥有用户定义的专属名称。
对比普通函数和 lambda 函数的 “命名” 差异:
普通函数:用
def
定义时,必须指定一个函数名(比如def add(x,y): ...
中的add
),这个名字是函数的 “标识”,会被永久绑定到函数对象上,方便后续反复调用。
例如:python
运行
def add(x, y): # 函数名是add,是用户显式定义的 return x + y print(add.__name__) # 输出:add(函数自带“名字”属性)
lambda 函数:用
lambda
定义时,不需要也不能指定函数名,它直接生成一个 “没有名字” 的函数对象。
例如:python
运行
lambda x, y: x + y # 没有任何名字,直接是一个函数对象
即使你把它赋值给变量(比如
f = lambda x,y: x+y
),这个变量名也只是 “临时标签”,不是函数本身的名字。此时函数的__name__
属性固定为<lambda>
(而非变量名):python
运行
f = lambda x, y: x + y print(f.__name__) # 输出:<lambda>(不是f)
为什么设计成 “匿名”?
lambda 的匿名特性,是为了适配 **“临时使用一次”** 的场景。比如在 PySpark 中用
map
、reduce
等方法时,往往只需要一个简单的临时函数来处理数据,用完就不再需要。这时用匿名的 lambda,比专门用def
定义一个有名字的函数更简洁。简单说:普通函数是 “有名有姓” 的 “常驻居民”,lambda 是 “无名无姓” 的 “临时过客”—— 这就是它被称为 “匿名函数” 的原因。
7.小节总结
8.给自己的话
这里的我在运行pyspark代码的时候其实报错出不来结果的,但是请听一下我的良苦用心:
我在上述的csdn博客中已近提及了,首先我的代码的逻辑是正确没错的,主要的问题是现在的环境的版本不兼容的问题,我的python解释器的版本是3.12,PyCharm中下载的pyspark第三方库的版本是3.5.5,而我的jdk的版本是jdk1.8.0_181。
通过查阅资料,我已经知道处理环境不兼容的方法:当前的python解释器版本过新,可能许多pyspark这样的第三方库的环境的API和PyCharm和python都没有自己处理好。
目前最稳定且推荐的是pyspark3.5.1和Python解释器的3.11.x的组合,而同时pyspark3.5以上的版本是要求java11以上的版本的,而我的是以前老师给过的很稳定的java8,但是前几天手残还把java8换成了java12,又是环境不兼容的问题更大了,连idea都差点崩掉,因为包括虚拟机、Maven和许多其他配置都是用的配置的环境变量的java8,这样为了解决一个小小的pyspark的运行出来的结果,要牵一发而动全身,过于危险,万一以前写过的代码因为我的随意更换java、Python的版本而宕机,是万万不可且得不偿失的。
况且,在这里学习的pyspark是spark1.0的最基础的RDD部分,搞通代码的逻辑部分即可了,况且最本质的spark是一款分布式处理的大数据框架,现在看的视频学的是古老的SparkConf,SparkContext这样的环境的入口对象,我之前和团队一起培训的时候都接触过最新的spark2.0以上的dataframe,和SparkSession入口了,而且实实在在的在虚拟机上搞了多节点,真正做到了分布式和spark的新的、兼容性更强、功能更加齐全的spark2.0以上的新的功能语法的熟悉和学习了,在这里冒着系统全部崩溃和学习远古技术的得不偿失和高风险,实在没有必要。
好了,又一篇博客和代码写完了,励志一下吧,下一小节等等继续:
听着,你个狗娘养的混蛋 —— 你以为写这博客、死磕这些破代码是在浪费时间?错了。你现在经历的每一次报错、每一次版本冲突、每一次想砸键盘的冲动,都是在给你的意志力上锈 —— 不,是上钢!
环境不兼容?版本对不上?那又怎样?这世上哪有他妈一帆风顺的事?戈金斯在海豹突击队训练时,脚指甲掉了一层又一层,背着几十磅的负重在泥里爬,教官骂他是废物,他还不是硬生生把自己炼成了传奇?你这点破环境问题,跟他在地狱周里流的血比起来,连屁都不算!
你说代码逻辑没错,只是环境坑?这就对了!这说明你他妈的脑子没生锈,你能分清主次,知道该死磕什么、该规避什么 —— 这不是懦弱,是他妈智慧!真正的狠角色,不是跟石头硬碰硬,是知道什么时候绕开障碍,继续往山顶冲。你以前跟团队搞分布式、玩 SparkSession 的时候就已经证明了:你能搞定真东西。现在这点破 RDD,不过是让你重温底层逻辑的垫脚石,不是让你栽跟头的坟墓。
别跟我抱怨 Java 版本、Python 版本那些破事。记住:痛苦是礼物。它不是来打垮你的,是来筛选你的。筛选出那些嘴上喊着 “太难了” 然后滚回舒适区的软蛋,剩下的 —— 比如你 —— 才能扛住真正的硬仗。你现在每多熬一分钟,每多查一份资料,每多骂一句 “操他妈的”,都是在给你的工具箱里多塞一把刀。以后遇到更大的坎,这些刀就能救命。
你以为戈金斯写《Can't Hurt Me》是为了告诉你他多牛逼?不!他是想让你知道:每个人都有一堆借口,一堆 “我做不到” 的理由,但真正的强者,会把这些借口踩在脚下,然后对着镜子里的自己说:“再来一轮,婊子养的。”
你现在就在做这件事。你没因为环境报错就放弃,没因为版本冲突就滚去刷视频,你他妈在分析问题、记录解决方案、理清逻辑 —— 这就是 “不找借口” 的活生生的例子。这比你跑通那行破代码重要一万倍,因为这是在训练你的大脑,让它习惯痛苦,习惯解决问题,习惯在混乱中找到秩序。
听着,混蛋 —— 这篇博客不是结束,是你下一轮战斗的号角。环境问题解决不了?那就先把逻辑刻进骨子里,等时机到了,一拳干碎那些版本壁垒。现在的每一次咬牙,都是在给未来的自己攒底气。
记住:你不是在学 PySpark,你是在锻造自己。锻造一个在专升本战场上能扛住压力、在代码堆里能找到出路、在生活操蛋时能笑着说 “再来” 的混蛋。这种锻造,环境带不走,版本改不了,只有你自己能决定它有多硬。
所以,别停。喝完这杯苦水,继续干。下一节,下一个报错,下一个他妈的挑战 —— 你来者不拒。因为你知道,你不是在跟代码较劲,你是在跟那个想偷懒、想放弃的自己较劲。而赢家,永远是那个更能忍、更能扛、更他妈不要命的混蛋。
动起来。现在就动。