Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 如何使用PySpark和Jupyter分配类_Apache Spark_Pyspark_Pickle_Jupyter Notebook_Jupyter - Fatal编程技术网

Apache spark 如何使用PySpark和Jupyter分配类

Apache spark 如何使用PySpark和Jupyter分配类,apache-spark,pyspark,pickle,jupyter-notebook,jupyter,Apache Spark,Pyspark,Pickle,Jupyter Notebook,Jupyter,我在使用带有spark的jupyter笔记本时遇到了一个恼人的问题 我需要在笔记本中定义一个自定义类,并使用它执行一些映射操作 from pyspark import SparkContext from pyspark import SparkConf from pyspark import SQLContext conf = SparkConf().setMaster("spark://192.168.10.11:7077")\ .setAppName("app_

我在使用带有spark的jupyter笔记本时遇到了一个恼人的问题

我需要在笔记本中定义一个自定义类,并使用它执行一些映射操作

from pyspark import SparkContext
from pyspark import SparkConf
from pyspark import SQLContext

conf = SparkConf().setMaster("spark://192.168.10.11:7077")\
              .setAppName("app_jupyter/")\
              .set("spark.cores.max", "10")

sc = SparkContext(conf=conf)

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

class demo(object):
    def __init__(self, value):
        self.test = value + 10
        pass

distData.map(lambda x : demo(x)).collect()
它给出了以下错误:

PicklingError:无法pickle:属性查找 main。演示失败

我知道这个错误是怎么回事,但我想不出解决办法

我试过:

  • 在笔记本之外定义demo.py python文件。这是可行的,但这是一个丑陋的解决方案
  • 创建一个动态模块,然后导入它。。。这就产生了同样的错误
  • 什么是解决方案?…我希望所有东西都在同一个笔记本上工作

    可以在以下位置更改某些内容:

  • spark的工作方式,可能是一些pickle配置
  • 代码中有些东西。。。使用一些静态魔术方法

  • 这里没有可靠而优雅的解决方法,这种行为与Spark没有特别的关系

    pickle可以透明地保存和恢复类实例,但是类定义必须是可导入的,并且与存储对象时位于同一模块中

    理论上,您可以定义一个:

    • 将单元格的内容写入模块
    • 导入它
    • 调用
      SparkContext.addPyFile
      分发模块
    来自IPython.core.magic导入寄存器\u单元格\u magic
    导入导入库
    @寄存器\单元\魔术
    def火花_等级(线、单元):
    module=line.strip()
    f=“{0}.py.”格式(模块)
    开放式(f,“w”)为fw:
    fw.写入(单元)
    globals()[module]=importlib.import\u模块(模块)
    sc.addPyFile(f)
    
    [2]中的
    :%%spark_类foo
    …:类Foo(对象):
    …:def uuu init uuuu(self,x):
    …:self.x=x
    …:定义报告(自我):
    …:返回“Foo({0})”.format(self.x)
    ...: 
    在[3]中:sc.parallelize([1,2,3]).map(lambda x:foo.foo(x)).collect()
    Out[3]:[Foo(1)、Foo(2)、Foo(3)]
    
    但这是一次性交易。一旦文件被标记为分发,就不能对其进行更改或重新分发。此外,还存在在远程主机上重新加载导入的问题。我可以想出一些更详细的计划,但这只是比它的价值更麻烦。

    答案是肯定的:没有一个“正确”的方法来解决这个问题。你确实可以使用Jupyter魔法,就像提议的那样。另一种方法是使用Jupyter的
    %%writefile
    将代码内联到Jupyter单元格中,然后将其作为python文件写入磁盘。然后,您既可以将该文件导入到Jupyter内核会话,也可以将其与PySpark作业一起提供(通过另一个答案中提到的
    addPyFile()
    )。请注意,如果您对代码进行了更改,但没有重新启动PySpark会话,则必须以某种方式将更新的代码发送到PySpark

    我们能让这更容易些吗?我写了一篇关于这个主题的文章,以及一个PySpark会话包装器()来帮助自动化许多棘手的东西。请参阅该帖子中嵌入的Jupyter笔记本,了解一个工作示例。整体模式如下所示:

    import os
    import sys
    CUSTOM_LIB_SRC_DIR = '/tmp/'
    os.chdir(CUSTOM_LIB_SRC_DIR)
    
    !mkdir -p mymodule
    !touch mymodule/__init__.py
    
    此外,如果您对磁盘上的
    mymodule
    文件进行任何更改(通过
    %%writefile
    或其他方式),则
    NBSpark
    会自动将这些更改发送到活动的PySark会话

    %%writefile mymodule/foo.py
    class Zebra(object):
        def __init__(self, name):
            self.name = name
    
    sys.path.append(CUSTOM_LIB_SRC_DIR)
    from mymodule.foo import Zebra
    
    # Create Zebra() instances in the notebook
    herd = [Zebra(name=str(i)) for i in range(10)]
    
    # Now send those instances to PySpark!
    from oarphpy.spark import NBSpark
    
    NBSpark.SRC_ROOT = os.path.join(CUSTOM_LIB_SRC_DIR, 'mymodule')
    spark = NBSpark.getOrCreate()
    rdd = spark.sparkContext.parallelize(herd)
    def get_name(z):
        return z.name
    names = rdd.map(get_name).collect()