【问题标题】:'list' object has no attribute 'foreach''list' 对象没有属性 'foreach'
【发布时间】:2021-01-04 09:27:57
【问题描述】:

我正在尝试复制 the given code 以查看 foreach 的工作原理,我尝试使用以下代码:

rdd = sc.parallelize([1,2,3,4,5])

def f(a):
    print(a)

rdd.collect().foreach(f)

但它给出了以下错误:

AttributeError: 'list' 对象没有属性 'foreach'

我理解collect() 的返回类型是array(它是列表)并且它没有与之关联的foreach 属性的错误,但是我不明白这怎么行不通如果它在官方spark 3.0.1 文档中给出。我错过了什么。我正在使用Spark 3.0.1

【问题讨论】:

  • rdd.collect.foreach(println) 是 Scala 构造,我相信。
  • @philantrovert 这就是我在代码中使用f() 的原因,现在这也有什么不同吗?
  • 它确实适用于 Scala,但为什么不在 python 中,因为我保留了语法 pythonic @philantrovert

标签: apache-spark rdd


【解决方案1】:

rdd.collect() 是一个将数据收集到驱动程序的 Spark 操作。 collect 方法返回一个列表,因此如果您想打印出列表的元素,只需执行以下操作:

rdd = sc.parallelize([1,2,3,4,5])

def f(a):
    print(a)

res = rdd.collect()

[f(e) for e in res]

# output
# 1
# 2
# 3
# 4
# 5

另一种方法是使用您的示例中提到的另一个操作foreach,例如rdd.foreach(f)。虽然,由于 Spark 的分布式特性,不能保证 print 命令会将数据发送到驱动程序的输出流。这实质上意味着您永远无法看到这些数据被打印出来。

这是为什么呢?因为 Spark 有两种部署模式,clusterclient 模式。在集群模式下,驱动程序在集群中的任意节点上运行。另一方面,在客户端模式下,驱动程序在您提交 Spark 作业的机器上运行,因此,Spark 驱动程序和您的程序共享相同的输出流。因此,您应该始终能够看到程序的输出。

相关链接

【讨论】:

  • 我知道打印列表的解决方案,我的问题是为什么 foreach 没有根据文档正常工作。如果它有效,那么我在这里缺少什么?
  • 在您的示例中,您正在执行rdd.collect().foreach(f),正如提到的rdd.collect() 将返回一个列表。当然 python list 没有foreach 方法,这就是您发布错误的原因(AttributeError: 'list' object has no attribute 'foreach')。
  • 我添加了一些关于在不同模式下打印结果的更多细节。顺便说一句,如果您在数据块上运行测试,您的作业将以集群模式运行。所以不要指望看到rdd.foreach(f)打印任何东西
猜你喜欢
  • 1970-01-01
  • 2020-08-09
  • 2019-03-19
  • 2014-06-05
  • 2021-07-26
  • 2019-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多