PySpark中mapPartitionsWithIndex等map类算子生成器函数问题 - return\yield

news/2025/3/1 17:43:11/

PySpark中mapPartitionsWithIndex等map类算子生成器函数问题 - return\yield

顾名思义,本文讲述了map算子生成器函数的相关问题——return 和 yield的使用。
首先先讲结论,在使用map等迭代生成的算子时最好使用yield

1、问题产生

在写代码的过程中,希望使用mapPartitionsWithIndex算子实现对每个分区内数据的操作。
具体是选择特定分区的索引,并赋值给新的变量。

def f(index,iter):if index==1 or index==42:return [index,list(iter)]a=data_rdd.mapPartitionsWithIndex(f)
a.take(2)

该函数,理论上是将分区为1和42的数据返回,由于个人习惯默认使用return来实现。❌

实际上这样是错误的处理方式,会编译错误 ❗

Caused by: org.apache.spark.api.python.PythonException: Traceback (most recent call last):File "/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/spark/python/pyspark/worker.py", line 372, in mainprocess()File "/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/spark/python/pyspark/worker.py", line 367, in processserializer.dump_stream(func(split_index, iterator), outfile)File "/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/spark/python/pyspark/serializers.py", line 390, in dump_streamvs = list(itertools.islice(iterator, batch))File "/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/spark/python/pyspark/rdd.py", line 1350, in takeUpToNumLeftiterator = iter(iterator)
TypeError: 'NoneType' object is not iterable

这里显示迭代器的传参异常。

2、问题解决思路

产生这样的问题主要是,在 PySpark 中,mapPartitionsWithIndex 这样的操作需要一个生成器函数,而== yield 是 Python 中实现生成器的关键字==。理解为什么需要 yield 而不是 return 需要理解生成器与普通函数的区别。

2.1、生成器和普通函数的区别

  • 普通函数(使用 return):当你在一个普通函数中使用 return 时,函数会立即停止执行并返回一个值。返回值可以是一个单一值或一个集合,但执行完之后函数就终止了。
  • 生成器函数(使用 yield):生成器是一个特殊类型的函数,它会在执行时“暂停”并返回一个值,但并不会终止。每次调用生成器时,它会从上次暂停的位置继续执行,并且可以产生多个值,而不仅仅是返回一个值。生成器是迭代器的一种形式。

2.2、mapPartitionsWithIndex 中为什么需要 yield 而不是 return

在 PySpark 中,mapPartitionsWithIndex 期望的是一个生成器函数,它必须能够按需生成结果,而不是一次性返回所有结果。因此,yield 是必须的。

  • mapPartitionsWithIndex 的工作方式:这个函数会遍历 RDD 的每个分区,并为每个分区提供一个迭代器。它希望接收到的是一个生成器对象,而不是一个单一的返回值。这样,它就可以按需获取每个分区的数据结果,而不是一次性返回所有结果

    • 当我们使用 yield 时,生成器函数不会结束,而是“暂停”并返回一个值mapPartitionsWithIndex 会逐个获取这些值。
    • 如果使用 return,则函数会立即返回并终止,无法继续生成多个值。这样 mapPartitionsWithIndex 将无法按需接收每个分区的结果。

3 Conclusion

当然实际上,部分场景下使用return是没问题的。😁
在之前根本没发现这一问题,哈哈哈。所以,之后写的时候还是注意这一问题。
有做相关方向的欢迎交流哦!!!🥳🥳🥳


http://www.ppmy.cn/news/1575831.html

相关文章

github上传代码(自用)

github上传代码(自用) 前提:git已与github完成秘钥连接配置 一、克隆仓库法: 把远程仓库克隆到本地,会自动生成仓库配置,不用自己连接 1、github建立远程仓库 2、新手引导(创建仓库时不要创…

UEditor集成Markdown编辑功能方案

分步解决方案: 1. 推荐免费开源Markdown库 推荐使用 markdown-it(MIT协议) 官网:https://github.com/markdown-it/markdown-it 特点:轻量级(15KB)、扩展性强、支持CommonMark规范、中文文档丰…

单片机开发为什么不用C++?

最近受到很多初学者的灵魂拷问,单片机需要学C吗? 还别说,问这问题的还挺多的,今天以一篇文章来说下。 很多小白觉得,C语言这老古董,语法简陋得像石器时代的产物,为什么还牢牢霸占着单片机开发的…

【Netty】五种经典 IO 模型详解,附各种模型流程图及流程详解

相关概念 同步:线程自己去获取结果(一个线程) 异步:线程自己不去获取结果,而是由其它线程送结果(至少两个线程) 同步阻塞、同步非阻塞、同步多路复用、异步阻塞(没有此情况&#x…

多线程视频处理代码

1. 什么是多线程 线程是进程中的一个执行单元,是操作系统进行调度的最小单位。一个进程可以包含多个线程,这些线程共享进程的资源,如内存和文件描述符,但每个线程有自己的程序计数器、寄存器和栈。 多线程是指在同一个进程中并发…

【Docker】Dify+ollama+deepseek(打造本地私有化大模型)

最近很流行私有化部署dp,之前已经尝试过ollamawebuideepseek本地化部署,但是体验感官上不是很多,特别卡顿。然后今天突然了解到Dify,也支持私有化部署大模型。而且似乎功能更加强大,那不得实操一下啊。 1.初识Dify D…

用pyside6创建一个界面并实现一个小功能且能打包成问题记录

现在我们要开发一个程序,让用户输入一段文本包含:员工姓名、薪资、年龄。该程序可以把薪资在 2万 以上、以下的人员名单分别打印出来。 1用designer创建界面并生成UI文件; 2直接调用ui文件实现功能; from PySide6.QtWidgets im…

爬虫项目:使用Python爬虫从电商平台采集评论数据并进行情感分析

文章目录 1. 环境搭建1.1 安装 Python1.2 安装依赖库2. 分析目标网站2.1 选择目标电商平台2.2 分析网页结构3. 采集 Amazon 评论数据4. 情感分析4.1 安装 TextBlob4.2 分析情感4.3 情感分类5. 完整示例7. 注意事项8. 总结在电商数据分析中,商品评论是了解用户反馈和产品表现的…