在Zeppelin中使用Spark时出现导入类找不到的异常
解决Zeppelin中Spark自定义类找不到的问题
我之前在Zeppelin里跑Spark代码也碰到过类似的类找不到坑,结合你给出的代码片段,大概率是这几个原因导致的,咱们一步步来排查解决:
1. 先补全截断的代码,修复语法错误
你代码里utcFormat = new Simp...明显没写完,这会直接导致编译器无法正确解析整个Pos类,后续自然找不到这个类。先把这部分补全,比如你应该是要创建UTC时区的SimpleDateFormat,参考下面的完整写法:
%spark import java.io.Serializable import java.text.{ParseException, SimpleDateFormat} import java.util.{Calendar, SimpleTimeZone} class Pos(val pos: String) extends Serializable { if (pos.length != 12) { throw new IllegalArgumentException(s"[${pos}] seems not a valid pos string") } private val cstFormat = new SimpleDateFormat("yyyyMMddHHmm") // 补全UTC格式的定义,加上时区设置 private val utcFormat = new SimpleDateFormat("yyyyMMddHHmm") utcFormat.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")) // 可以按需添加类的方法,比如解析时间的逻辑 def getUtcTime(): Calendar = { val cal = Calendar.getInstance() cal.setTime(utcFormat.parse(pos)) cal } }
2. 调整Zeppelin中类的作用域
Zeppelin的Spark解释器有自己的类加载机制,如果自定义类直接写在和业务代码同一段落里,有时候会因为作用域问题导致后续代码找不到类。这里有两个实用的解决办法:
- 单独段落定义类:新建一个Zeppelin段落,只放
Pos类的定义代码,用%spark开头,运行通过后,再在其他需要使用Pos类的段落里写业务代码。 - 把类放在object内部:将
Pos类嵌套在一个object里,这样Spark的类加载器更容易识别,使用的时候通过object来引用类:
%spark import java.io.Serializable import java.text.{ParseException, SimpleDateFormat} import java.util.{Calendar, SimpleTimeZone} // 用object包裹类 object PosWrapper { class Pos(val pos: String) extends Serializable { if (pos.length != 12) { throw new IllegalArgumentException(s"[${pos}] seems not a valid pos string") } private val cstFormat = new SimpleDateFormat("yyyyMMddHHmm") private val utcFormat = new SimpleDateFormat("yyyyMMddHHmm") utcFormat.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")) } } // 使用的时候这样引用 val posInstance = new PosWrapper.Pos("202405201234")
3. 替换成线程安全的日期API(可选但推荐)
你当前用的SimpleDateFormat不是线程安全的,在Spark分布式环境下容易出问题,建议换成Java 8+的DateTimeFormatter,它是线程安全的,而且代码更简洁:
%spark import java.io.Serializable import java.time.format.DateTimeFormatter import java.time.{ZoneId, ZonedDateTime} class Pos(val pos: String) extends Serializable { // 用require替代if判断,更符合Scala风格 require(pos.length == 12, s"[${pos}] seems not a valid pos string") private val cstFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm").withZone(ZoneId.of("Asia/Shanghai")) private val utcFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm").withZone(ZoneId.of("UTC")) def parseCstTime(): ZonedDateTime = ZonedDateTime.parse(pos, cstFormatter) }
4. 重置Spark解释器
如果上面的方法都试过还是不行,可能是Zeppelin的Spark上下文出现了异常。可以尝试:
- 在段落开头加上
%spark reset重置上下文 - 或者在Zeppelin的解释器管理页面,重启Spark解释器,然后重新运行类定义和业务代码段落
内容的提问来源于stack exchange,提问作者user9618434
相关产品推荐
相关产品推荐

