[英]Spark Scala: Task Not serializable error
我正在使用帶有 Scala 插件和火花庫的 IntelliJ 社區版。 我仍在學習 Spark 並且正在使用 Scala Worksheet。
我編寫了以下代碼來刪除字符串中的標點符號:
def removePunctuation(text: String): String = {
val punctPattern = "[^a-zA-Z0-9\\s]".r
punctPattern.replaceAllIn(text, "").toLowerCase
}
然后我閱讀了一個文本文件並嘗試刪除標點符號:
val myfile = sc.textFile("/home/ubuntu/data.txt",4).map(removePunctuation)
這給出了如下錯誤,任何幫助將不勝感激:
org.apache.spark.SparkException:在 org.apache.spark.util.ClosureCleaner$.ensureSerializable(/home/ubuntu/src/main/scala/Test.sc:294) 處的任務不可序列化在 org.apache.spark.util .ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(/home/ubuntu/src/main/scala/Test.sc:284) 在 org.apache.spark.util.ClosureCleaner$.clean(/home /ubuntu/src/main/scala/Test.sc:104) 在 org.apache.spark.SparkContext.clean(/home/ubuntu/src/main/scala/Test.sc:2090) 在 org.apache.spark。 rdd.RDD$$anonfun$map$1.apply(/home/ubuntu/src/main/scala/Test.sc:366) 在 org.apache.spark.rdd.RDD$$anonfun$map$1.apply(/home /ubuntu/src/main/scala/Test.sc:365) 在 org.apache.spark.rdd.RDDOOperationScope$.withScope(/home/ubuntu/src/main/scala/Test.sc:147) 在#worksheet# .#worksheet#(/home/ubuntu/src/main/scala/Test.sc:108) 引起:java.io.NotSerializableException:A$A21$A$A21 序列化堆棧:-對象不可序列化(類:A$ A21$A$A21,值:A$A21$A$A21@62db3891) - 字段(類:A$A21$A$A21$$anonfun$words$1,名稱:$ 外部,類型:類 A$A21$A$A21) - org.apache.spark.serializer.SerializationDebugger$.improveException(SerializationDebugger.scala: 40) 在 org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:46) 在 org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:100) 在 org.apache.spark.util.ClosureCleaner $.ensureSerializable(ClosureCleaner.scala:295) 在 org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:288) 在 org.apache.spark.util。 ClosureCleaner$.clean(ClosureCleaner.scala:108) at org.apache.spark.SparkContext.clean(SparkContext.scala:2094) at org.apache.spark.rdd.RDD$$anonfun$map$1.apply(RDD.scala) :370) 在 org.apache.spark.rdd.RDD$$anonfun$map$1.apply(RDD.scala:369) 在 org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151) 在 org .apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112) 在 org.ap ache.spark.rdd.RDD.withScope(RDD.scala:362) at org.apache.spark.rdd.RDD.map(RDD.scala:369) at A$A21$A$A21.words$lzycompute(Test. sc:27) 在 A$A21$A$A21.words(Test.sc:27) 在 A$A21$A$A21.get$$instance$$words(Test.sc:27) 在 A$A21$。 main(Test.sc:73) at A$A21.main(Test.sc) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect .DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.jetbrains.plugins.scala.worksheet.MyWorksheetRunner.main(MyWorksheetRunner.java:22)
正如 T. Gaweda 已經指出的那樣,您很可能在一個不可序列化的類中定義您的函數。 因為它是一個純函數,即它不依賴於封閉類的任何上下文,我建議您將它放入一個應該擴展Serializable
的伴隨對象中。 這將是 Scala 的 Java 靜態方法的等價物:
object Helper extends Serializable {
def removePunctuation(text: String): String = {
val punctPattern = "[^a-zA-Z0-9\\s]".r
punctPattern.replaceAllIn(text, "").toLowerCase
}
}
正如@TGaweda 所建議的那樣,Spark 的SerializationDebugger
非常有助於識別“從給定對象到有問題對象的序列化路徑”。 堆棧跟蹤中“序列化堆棧”之前的所有美元符號表示您的方法的容器對象是問題所在。
雖然在你的容器類上使用Serializable
是最簡單的,但我更喜歡利用 Scala 是一種函數式語言的事實,並將你的函數用作一等公民:
sc.textFile("/home/ubuntu/data.txt",4).map { text =>
val punctPattern = "[^a-zA-Z0-9\\s]".r
punctPattern.replaceAllIn(text, "").toLowerCase
}
或者,如果您真的想將事情分開:
val removePunctuation: String => String = (text: String) => {
val punctPattern = "[^a-zA-Z0-9\\s]".r
punctPattern.replaceAllIn(text, "").toLowerCase
}
sc.textFile("/home/ubuntu/data.txt",4).map(removePunctuation)
這些選項當然有效,因為正如您應該確認的那樣, Regex
是可序列化的。
在次要但非常重要的注意事項中,構建Regex
是昂貴的,因此為了性能,將其從轉換中排除 - 可能使用廣播。
閱讀堆棧跟蹤,有:
$outer,類型:A$A21$A$A21 類
這是一個很好的提示。 您的 lambda 是可序列化的,但您的類不可序列化。
當您創建 lambda 表達式時,此表達式將引用外部類。 您的情況下的外部類不可序列化,即未實現 Serializable 或其中一個字段不是 Serializable 的實例
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.