RDD创建和变量绑定

时间:2016-12-21 02:07:53

标签: python apache-spark pyspark lazy-evaluation

我有一个非常简单的代码:

def fun(x, n):
    return (x, n)

rdds = []
for i in range(2):
    rdd = sc.parallelize(range(5*i, 5*(i+1)))
    rdd = rdd.map(lambda x: fun(x, i))
    rdds.append(rdd)

a = sc.union(rdds)
print a.collect()

我原本期望输出如下:

[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 1), (6, 1), (7, 1), (8, 1), (9, 1)]

但是,输出如下:

[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1), (9, 1)]

至少可以说这是令人困惑的。

看来,由于对RDD的懒惰评估,用于创建RDD的i的值是它在调用collect()时所承受的值,即1(从上次运行开始) for循环。)

现在,元组的两个元素都来自i

但似乎,对于元组的第一个元素,i的值为0和1,而元组i的第二个元素的值为2。

有人可以解释一下发生了什么吗?

感谢。

2 个答案:

答案 0 :(得分:2)

只需更改

rdd = rdd.map(lambda x: fun(x, i))

rdd = rdd.map(lambda x, i=i: (x, i))

这只是关于Python,请看这个

  

https://docs.python.org/2.7/tutorial/controlflow.html#default-argument-values

答案 1 :(得分:0)

sc.parallelize()是一个即时执行的动作。因此,将使用i的值,即01

但是在rdd.map()的情况下,当您稍后致电i时,将仅使用collect()的最后一个值。

rdd = sc.parallelize(range(5*i, 5*(i+1)))
rdd = rdd.map(lambda x: fun(x, i))

这里rdd.map不会变换rdd,它只会创建DAG(Directed Acyclic Graph),即lambda函数不会应用于rdd的元素。

当你调用collect()时,将调用lambda函数,但到那时i的值为1.如果在调用collect之前重新分配i=10,那么{{1}的值将被使用。