pyspark getattr() 行为

pyspark getattr() behavior

注意到 PySpark 的一些奇怪行为,将不胜感激任何见解。

假设我有一个由简单元素组成的 RDD

from collections import namedtuple
Animal = namedtuple('Animal', ('name','age'))
a = Animal('jeff',3)
b = Animal('mike',5)
c = Animal('cathy',5)
rdd=sc.parallelize([a,b,c])

现在我有兴趣在一个简单的 class 中捕获该 RDD 的不同属性,例如使用 rdd.map(lambda s: getattr(s,'name')) 从每个元素中提取 name 属性。

所以这个 class

的对象
class simple():
    def __init__(self,name):
        self.name=name
    def get_value(self):
        self.value = rdd.map(lambda s: getattr(s,self.name)).collect()

将设置它们的 name 并从 RDD 中获取相应的 values

theAges = simple('age')
theAges.get_value()

然而,这遇到了一个错误,我认为集中在 lambda 表达式中的 self.name 上。第二个 class 工作正常

class simple2():
    def __init__(self,name):
        self.name=name
    def get_value(self):
        n=self.name
        self.value = rdd.map(lambda s: getattr(s,n)).collect() 

我添加的只是前面的调用 n=self.name 并将 n 传递给 lambda 而不是 self.name

所以我们无法在lambda内评估self.name的问题?我在纯 python 中创建了类似的情况(self.namelambda 中)并且没有错误,所以我认为这是 Spark 特定的。谢谢你的想法。

这是因为 pyspark 无法在 class 实例上创建闭包。在 get_value 范围内分配 n 允许 Spark 发送 pickled 函数,包括相当于对象属性别名的内容。到目前为止,解决方案似乎只是在函数范围内分配 class 属性(但不要指望它们会改变!)