Apache spark 如何使用PySpark和Jupyter分配类
我在使用带有spark的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_
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。演示失败
我知道这个错误是怎么回事,但我想不出解决办法
我试过:
这里没有可靠而优雅的解决方法,这种行为与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()