在pyspark中调用scala/java代码
原文地址:Using Scala code in PySpark applications (diogoalexandrefranco.github.io)
前言
虽然有充分的理由使用Python API开发Spark应用程序,但不可否认的是,Scala是Spark的母语。如果您需要PySpark不支持的功能,或者只想在Python应用程序中使用Scala库,那么这篇文章将展示如何将两者结合起来,并充分利用两者。
一、在PySpark应用程序中调用Scala代码
Pyspark在解释器和JVM之间建立了一个geteway ,也就是 Py4J 。我们可以用它来操作Java对象。
下面让我们编写一个最简单的Scala对象:
package com.test.spark object SayHello { def ditBonjour = println("Bonjour") }
然后,我们使用maven或sbt等工具构建它并将其打包为JAR:
$ mvn package Building jar: .../target/testspark-0.1.0-SNAPSHOT.jar
接下来,我们可以在启动pyspark shell的时候,使用--driver-class-path
添加这个jar包。 同时,我们可能还需要在--jars
参数包含这个jar包。
pyspark --master yarn --deploy-mode client --jars testspark-0.1.0-SNAPSHOT.jar --driver-class-path testspark-0.1.0-SNAPSHOT.jar
然后在交互界面中, 我们可以通过访问spark context(sc)的_jvm属性来访问我们的包:
>>> SayHello = sc._jvm.com.test.spark.SayHello >>> SayHello.ditBonjour() Bonjour
真正的项目从来没有那么简单!!!
在实际项目中,有几件事可能与上面的简单示例不同,这会带来一些复杂性。
依赖于外部库的Scala代码:
在这种情况下,我不可能总是通过简单地打包Scala代码并在–packages中提交具有依赖项的PySpark作业来获得成功。最简单的方法是打包一个也包含Scala依赖项的jar。我们可以使用sbt组装来实现这一点。
传递Spark对象:
在环境之间传递Spark对象时,必须将其显式装箱/取消装箱到java对象中。以下是几个常见的例子:
- SparkContext
// 如果您的Scala代码需要访问SparkContext(sc),那么python代码必须通过sc._ jsc,
// 并且您的Scala方法应该接收一个JavaSparkContext参数并将其取消绑定到Scala SparkContext。 import org.apache.spark.api.java.JavaSparkContext def method(jsc: JavaSparkContext) = { val sc = JavaSparkContext.toSparkContext(jsc) } - SQLContext
// Scala SQLContext 可以通过发送 sqlContext._ssql_ctx 从 python 传递。 这将在 Scala 端无需任何转换即可使用。
- RDDs
// 您可以通过rdd将它们从Python传递到Scala_jrdd。在Scala方面,可以通过访问jrdd来解除JavaRDD(jrdd)的绑定。rdd。将其转换回Python时,可以执行以下操作: from pyspark.rdd import RDD pythonRDD = RDD(jrdd, sc)
- DataFrames
// 要从python发送数据帧(df),必须传递df_jdf属性。将Scala数据帧返回python时,可以通过以下方式在python端进行转换: from pyspark.sql import DataFrame pythonDf = DataFrame(jdf, sqlContext)