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

embedded/2025/3/5 3:58:29/

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/embedded/170076.html

相关文章

我们应该如何优化UI(基于UGUI)

这是一道面试题,下面,我们来详细分析这个问题。 目录 1. 减少 Draw Call 合理设置图集 避免材质和 Shader 的频繁切换 减少 UI 元素的重叠 2. 优化UI布局 3. 优化UI元素的渲染 4.优化UI动画 5. 优化 UI 事件处理 6. 运行时优化 1. 减少 Draw C…

初阶数据结构(C语言实现)——3顺序表和链表(1)

目录 【本节目标】1. 线性表2.顺序表2.1概念及结构2.2 接口实现2.2.0 动态顺序表2.2.1 顺序表初始化SLInit()2.2.2 销毁和打印2.2.3 尾插SLPushBack()2.2.4 尾删SLPopBack()2.2.5 头插2.2.6 头删2.2.7 插入…

天佐.乾坤袋 基于抽屉式文件存储的NoSql数据库

天佐.乾坤袋 天佐.乾坤袋 简介 天佐.乾坤袋 基于抽屉式文件存储的NoSql数据库,可用于文件打包,数据整合,加密存放等多种用途。可以方便快捷的搭建和部署存储应用的系统。 传说: 弥勒所有,专做储物之用。拥有不可思议之力&#x…

优云智算:借助强大镜像社区,开启AI算力新纪元!

🎁个人主页:我们的五年 🔍系列专栏:Linux网络编程 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 ​ 目录 前言: 平台介绍: …

利用Java爬虫获取1688店铺所有商品信息:实战指南

在电商领域,获取1688店铺的所有商品信息对于市场分析、选品决策和竞争情报收集至关重要。1688作为国内领先的B2B电商平台,提供了丰富的商品数据。通过Java爬虫技术,我们可以高效地获取1688店铺的所有商品信息。本文将详细介绍如何利用Java爬虫…

从零开始:H20服务器上DeepSeek R1 671B大模型部署与压力测试全攻略

前言 最近,我有幸在工作中接触到了DeepSeek R1 671B模型,这是目前中文开源领域参数量最大的高质量模型之一。DeepSeek团队在2024年推出的这款模型,以其惊人的6710亿参数量和出色的推理性能,引起了业界广泛关注。 作为一名AI基础…

版图自动化连接算法开发 00002 ------ 添加一个中间点实现 Manhattan 方式连接两个给定的坐标点

版图自动化连接算法开发 00002 ------ 添加一个中间点实现 Manhattan 方式连接两个给定的坐标点 引言正文引言 必读文章 ------ 版图自动化连接算法开发 00001 ------ 直接连接两个给定的坐标点 之前,我们实现了两个坐标点之间的直接连接,属于最简单的布线方式,但是对于光…

Python使用pyobdc库和tkinter框架连接数据库

要使用 pyodbc 和 tkinter 实现动态连接数据库的功能,可以通过以下步骤实现: 使用 tkinter 创建一个图形界面,让用户输入数据库连接信息(如服务器地址、数据库名称、用户名和密码)。通过 pyodbc 动态连接到数据库&…