我正在尝试导入spark.implicits._ 显然,这是scala中类中的一个对象。 当我用这样的方法导入它时:
def f() = {
val spark = SparkSession()....
import spark.implicits._
}
它工作正常,但我正在编写一个测试类,我想让这个导入可用于所有测试 我试过了:
class SomeSpec extends FlatSpec with BeforeAndAfter {
var spark:SparkSession = _
//This won't compile
import spark.implicits._
before {
spark = SparkSession()....
//This won't either
import spark.implicits._
}
"a test" should "run" in {
//Even this won't compile (although it already looks bad here)
import spark.implicits._
//This was the only way i could make it work
val spark = this.spark
import spark.implicits._
}
}
这不仅看起来很糟糕,我也不想为每次测试做这件事 什么是"正确"这样做的方式?
答案 0 :(得分:18)
您可以执行类似于Spark测试套件中所做的操作。例如,这将起作用(受SQLTestData
启发):
class SomeSpec extends FlatSpec with BeforeAndAfter { self =>
var spark: SparkSession = _
private object testImplicits extends SQLImplicits {
protected override def _sqlContext: SQLContext = self.spark.sqlContext
}
import testImplicits._
before {
spark = SparkSession.builder().master("local").getOrCreate()
}
"a test" should "run" in {
// implicits are working
val df = spark.sparkContext.parallelize(List(1,2,3)).toDF()
}
}
或者你可以直接使用SharedSQLContext
之类的东西,它提供testImplicits: SQLImplicits
,即:
class SomeSpec extends FlatSpec with SharedSQLContext {
import testImplicits._
// ...
}
答案 1 :(得分:9)
我认为SparkSession.scala文件中的GitHub代码可以给你一个很好的提示:
/**
* :: Experimental ::
* (Scala-specific) Implicit methods available in Scala for converting
* common Scala objects into [[DataFrame]]s.
*
* {{{
* val sparkSession = SparkSession.builder.getOrCreate()
* import sparkSession.implicits._
* }}}
*
* @since 2.0.0
*/
@Experimental
object implicits extends SQLImplicits with Serializable {
protected override def _sqlContext: SQLContext = SparkSession.this.sqlContext
}
这里" spark" in" spark.implicits ._"就是我们创建的sparkSession对象。
Here是另一个参考!
答案 2 :(得分:5)
我只是实例化SparkSession并在使用之前,"导入含义"。
@transient lazy val spark = SparkSession
.builder()
.master("spark://master:7777")
.getOrCreate()
import spark.implicits._
答案 3 :(得分:0)
要在将任何rdd转换为数据集之前,创建一个sparksession对象并使用spark.implicit ._。
赞:
val spark = SparkSession
.builder
.appName("SparkSQL")
.master("local[*]")
.getOrCreate()
import spark.implicits._
val someDataset = someRdd.toDS
答案 4 :(得分:0)
它必须在scala中使用val vs var做一些事情。
例如以下操作不起作用
var sparkSession = new SparkSession.Builder().appName("my-app").config(sparkConf).getOrCreate
import sparkSession.implicits._
但是遵循
sparkSession = new SparkSession.Builder().appName("my-app").config(sparkConf).getOrCreate
val sparkSessionConst = sparkSession
import sparkSessionConst.implicits._
我对scala非常熟悉,所以我只能猜测其原因与为什么我们只能在java的闭包内部使用声明为final的外部变量相同。
答案 5 :(得分:0)
感谢@ bluenote10提供有用的答案,我们可以再次简化它,例如,没有辅助对象testImplicits
:
private object testImplicits extends SQLImplicits {
protected override def _sqlContext: SQLContext = self.spark.sqlContext
}
通过以下方式:
trait SharedSparkSession extends BeforeAndAfterAll { self: Suite =>
/**
* The SparkSession instance to use for all tests in one suite.
*/
private var spark: SparkSession = _
/**
* Returns local running SparkSession instance.
* @return SparkSession instance `spark`
*/
protected def sparkSession: SparkSession = spark
/**
* A helper implicit value that allows us to import SQL implicits.
*/
protected lazy val sqlImplicits: SQLImplicits = self.sparkSession.implicits
/**
* Starts a new local spark session for tests.
*/
protected def startSparkSession(): Unit = {
if (spark == null) {
spark = SparkSession
.builder()
.master("local[2]")
.appName("Testing Spark Session")
.getOrCreate()
}
}
/**
* Stops existing local spark session.
*/
protected def stopSparkSession(): Unit = {
if (spark != null) {
spark.stop()
spark = null
}
}
/**
* Runs before all tests and starts spark session.
*/
override def beforeAll(): Unit = {
startSparkSession()
super.beforeAll()
}
/**
* Runs after all tests and stops existing spark session.
*/
override def afterAll(): Unit = {
super.afterAll()
stopSparkSession()
}
}
最后我们可以使用SharedSparkSession
进行单元测试并导入sqlImplicits
:
class SomeSuite extends FunSuite with SharedSparkSession {
// We can import sql implicits
import sqlImplicits._
// We can use method sparkSession which returns locally running spark session
test("some test") {
val df = sparkSession.sparkContext.parallelize(List(1,2,3)).toDF()
//...
}
}
答案 6 :(得分:0)
好吧,我一直在每个被调用的方法中重用现有的SparkSession。通过在方法内部创建本地val-
val spark: org.apache.spark.sql.SparkSession = org.apache.spark.sql.SparkSession.active
然后
import spark.implicits._
答案 7 :(得分:0)
我知道这是旧文章,但是只是想分享我的观点,我认为这是您声明sparkSession的方式的问题。当您将sparkSession声明为var时,它不会使其不可变,这可以在以后更改时间。因此它不允许导入隐式内容,因为它可能导致歧义,因为在以后的阶段它可以更改,因为在val情况下它可能不相同