繁体   English   中英

在pyspark RDD中迭代用户定义的类对象

[英]Iterating user-defined class objects inside a pyspark RDD

我正在从csv读取数据,并将该数据转换为python类对象。 但是,当我尝试使用用户定义的类对象遍历该rdd时,出现类似以下错误:

_pickle.PicklingError: Can't pickle <class '__main__.User'>: attribute lookup User on __main__ failed

我在这里添加了部分代码,

class User:
    def __init__(self, line):
        self.user_id = line[0]
        self.location = line[1]
        self.age = line[2]

def create_user(line):
    user = User(line)
    return user

def print_user(line):
    user = line
    print(user.user_id)

conf = (SparkConf().setMaster("local").setAppName("exercise_set_2").set("spark.executor.memory", "1g"))
sc = SparkContext(conf = conf)
users = sc.textFile("BX-Users.csv").map(lambda line: line.split(";"))  
users_objs = users.map(lambda entry: create_user(entry))
users_objs.map(lambda entry: print_user(entry))

对于上面的代码,我得到如下结果:

PythonRDD[93] at RDD at PythonRDD.scala:43

CSV数据源URL(需要zip提取): 此处

更新:将代码更改为包括收集将再次导致错误,我仍然必须尝试使用​​Pickle。 我以前从未尝试过这样做,如果您有样品,我可以轻松完成。

users_objs = users.map(lambda entry: create_user(entry)).collect()

使用时

def create_user(line):
    user = User(line)
    return user

直接在地图调用中,这意味着您的节点必须可以访问User类。 通常,这意味着它需要可序列化/可拾取。 节点将如何使用该类或知道它是什么(除非您具有通用的NFS挂载或类似的东西)? 这就是为什么您会收到泡菜错误。 要使您的User类可腌,请阅读以下内容: https : //docs.python.org/2/library/pickle.html

此外,您没有在RDD上执行collect() ,这就是为什么您PythonRDD[93] at RDD at PythonRDD.scala:43看到PythonRDD[93] at RDD at PythonRDD.scala:43 它仍然只是一个RDD,您的数据在节点上。

好的,找到了解释。 将类存储在单独的文件中将使这些类自动可腌制 因此,我将User类存储在user.py中,并将以下导入添加到我的代码中。

from user import User

User.py的内容

class User:
    def __init__(self, line):
        self.user_id = line[0]
        self.location = line[1]
        self.age = line[2]

正如前面的答案中提到的,我可以在创建的User对象上收集用户(RDD方法)。 因此,以下代码将根据需要打印所有用户ID。

for user_obj in users.map(lambda entry: create_user(entry)).collect():
    print_user(user_obj)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM