如何在Apache Spark(pyspark)中使用自定义类?

时间:2015-06-27 20:25:50

标签: python apache-spark python-module pyspark

我编写了一个在python中实现分类器的类。我想使用Apache Spark来使用此分类器并行化大量数据点的分类。

  1. 我在拥有10个奴隶的群集上使用Amazon EC2进行设置,基于python的Anaconda发行版附带的ami。 ami让我可以远程使用IPython Notebook。
  2. 我已经在文件调用BoTree.py中定义了类BoTree,该文件调用了主文件夹/root/anaconda/lib/python2.7/,这是我所有的python模块都在哪里
  3. 我检查过在从主服务器运行命令行spark时我可以导入和使用BoTree.py(我只需要从编写导入BoTree开始,我的类BoTree就可用了
  4. 我已经使用spark的/root/spark-ec2/copy-dir.sh脚本在我的群集中复制/python2.7/目录。
  5. 我已经闯入其中一个奴隶并尝试在那里运行ipython,并且能够导入BoTree,所以我认为该模块已成功发送到集群(我也可以看到BoTree.py文件在... / python2.7 /文件夹中)
  6. 在我检查过的主人身上,我可以使用cPickle来挑选和解开一个BoTree实例,我理解这是pyspark的序列化器。
  7. 然而,当我执行以下操作时:

    import BoTree
    bo_tree = BoTree.train(data)
    rdd = sc.parallelize(keyed_training_points) #create rdd of 10 (integer, (float, float) tuples
    rdd = rdd.mapValues(lambda point, bt = bo_tree: bt.classify(point[0], point[1]))
    out = rdd.collect()
    

    Spark因错误而失败(我认为只是相关的一点):

      File "/root/spark/python/pyspark/worker.py", line 90, in main
        command = pickleSer.loads(command.value)
      File "/root/spark/python/pyspark/serializers.py", line 405, in loads
        return cPickle.loads(obj)
    ImportError: No module named BoroughTree
    

    任何人都可以帮助我吗?有点绝望......

    由于

2 个答案:

答案 0 :(得分:15)

可能最简单的解决方案是在创建pyFiles时使用SparkContext参数

from pyspark import SparkContext
sc = SparkContext(master, app_name, pyFiles=['/path/to/BoTree.py'])

放置在那里的每个文件都会发送给工作人员并添加到PYTHONPATH

如果您在交互模式下工作,则必须先使用sc.stop()停止现有上下文,然后才能创建新的上下文。

还要确保Spark worker实际上使用的是Anaconda发行版而不是默认的Python解释器。根据您的描述,这很可能是问题所在。要设置PYSPARK_PYTHON,您可以使用conf/spark-env.sh个文件。

另一方面,将文件复制到lib是一个相当混乱的解决方案。如果你想避免使用pyFiles推送文件,我建议你创建普通的Python包或Conda包以及正确的安装。通过这种方式,您可以轻松跟踪已安装的内容,删除不必要的软件包并避免一些难以调试的问题。

答案 1 :(得分:11)

获取SparkContext后,也可以使用addPyFile随后将模块发送给每个工作人员。

sc.addPyFile('/path/to/BoTree.py')

pyspark.SparkContext.addPyFile(path) documentation