Apache spark 在pyspark中将python函数传递给Scala RDD
我有一个scala库,它(简单地说)接收一个函数,将其应用于一个RDD并返回另一个RDDApache spark 在pyspark中将python函数传递给Scala RDD,apache-spark,pyspark,rdd,py4j,Apache Spark,Pyspark,Rdd,Py4j,我有一个scala库,它(简单地说)接收一个函数,将其应用于一个RDD并返回另一个RDD def runFunction(rdd: RDD, function: Any => Any) = { .... val res = rdd.map(function) ... } 在scala中,用法是 import mylibrary.runFunction runFunction(myRdd, myScalaFun) 这个库打包在一个jar中,我现在也要在pytho
def runFunction(rdd: RDD, function: Any => Any) = {
....
val res = rdd.map(function)
...
}
在scala中,用法是
import mylibrary.runFunction
runFunction(myRdd, myScalaFun)
这个库打包在一个jar中,我现在也要在python中使用它。我想做的是用Python加载这个库,并向它传递一个Python函数。Python中的用法如下:
spark._jvm.mylibrary.runFunction(myPythonRdd, myPythonFun)
这将允许我使用python函数和Scala函数,而无需将整个库移植到python。这是否可以通过在Python和JVM之间来回切换的Spark功能实现?PySpark中Python和JVM的通信方式有一些微妙之处。桥接器使用Java对象,即
JavaRDD
和非RDD
,这些对象需要在Scala中显式取消绑定。由于Scala函数采用RDD
,因此需要在Scala中编写一个包装器,该包装器接收JavaRDD
,并首先执行取消装箱:
def runFunctionWrapper(jrdd: JavaRDD, ...) = {
runFunction(jrdd.rdd, ...)
}
那就这样说吧
spark._jvm.mylibrary.runFunctionWrapper(myPythonRdd._jrdd, ...)
请注意,根据Python约定,\uJRDD
被视为PythonRDD
类的私有成员,因此这实际上依赖于未记录的实现细节。这同样适用于SparkContext
的\u jvm
成员
真正的问题是为了应用函数
,将Scala回调到Python中。在PySpark中,Python RDD的map()
方法创建org.apache.spark.api.Python的一个实例
.PythonFunction
,它保存对Python映射器函数及其环境的pickle引用。然后,每个RDD分区被序列化,并与通过TCP发送到与Spark executor共址的Python进程的pickle内容一起,在该进程中,分区被反序列化并迭代。最后,结果再次序列化并发送回执行器。整个过程由org.apache.spark.api.python.PythonRunner
的一个实例进行编排。这与围绕Python函数构建包装器并将其传递给RDD
实例的map()
方法非常不同
我认为最好是简单地在Python中复制
runFunction
的功能,或者(在性能方面更好)在Scala中复制myPythonFun
的功能。或者,如果你所做的事情可以交互完成,那么按照@EnzoBnl的建议,利用齐柏林飞艇或Polynote等多语言笔记本环境。在我看来,所有这些很快就会变得难以维护。。。如果您不只是因为需要/喜欢python生态系统(对于dataviz,ml…)而使用scala,我建议您考虑一下,使用fine Spark支持,将两种语言无缝地混合到一个笔记本中。