在简单的正则表达式替换上获取NPE(Scala on Spark)

时间:2017-06-04 07:41:40

标签: scala apache-spark nullpointerexception emr

我编写了一个简单的代码来解析一个大的XML文件(从中提取行,清理文本,并从中删除任何html标记)。

我在字符串上调用.replaceAllIn时看到NullPointerException,这是非空的。

有趣的是,我在本地运行代码时没有错误,使用来自磁盘的输入,但是当我在AWS EMR上运行相同的代码时,我得到NullPointerException,从S3加载输入文件。

以下是相关代码:

val HTML_TAGS_PATTERN = """<[^>]+>""".r

// other code here...

spark
.sparkContext
.textFile(pathToInputFile, numPartitions)
.filter { str => str.startsWith("  <row ") }
.toDS()
.map { str =>

  Locale.setDefault(new Locale("en", "US"))

  val parts = str.split(""""""")

  var title: String = ""
  var body: String = ""

  // some code ommitted here

  title = StringEscapeUtils.unescapeXml(title).toLowerCase.trim
  body = StringEscapeUtils.unescapeXml(body).toLowerCase // decode xml entities


  println("before replacing, body is: "+body)

  // NEXT LINE TRIGGERS NPE
  body = HTML_TAGS_PATTERN.replaceAllIn(body, " ") // take out htmltags

}

我尝试的事情:

  • 在致电replaceAllIn之前打印字符串,以确保它不是null

  • 确保区域设置不为空

  • 打印出异常消息和stacktrace:它只是告诉我该行是NullPointerException发生的地方。没有更多

我的本​​地设置和AWS EMR之间的不同之处:

  • 在我的本地设置中,我从磁盘加载输入文件,在EMR上我从s3加载它。

  • 在我的本地设置中,我以独立模式运行Spark,在EMR上以集群模式运行。

我的机器和AWS EMR上的其他所有内容都相同:Scala版本,Spark版本,Java版本,群集配置......

我一直在努力解决这个问题几个小时,我无法想到其他任何事情。

修改

我已将r()的电话转移到map{}机构内,如下所示:

val HTML_TAGS_PATTERN = """<[^>]+>"""

// code ommited

.map{

   body = HTML_TAGS_PATTERN.r.replaceAllIn(body, " ")    

 }

这也产生 NPE ,具有以下stracktrace:

java.lang.NullPointerException
    at java.util.regex.Pattern.<init>(Pattern.java:1350)
    at java.util.regex.Pattern.compile(Pattern.java:1028)
    at scala.util.matching.Regex.<init>(Regex.scala:191)
    at scala.collection.immutable.StringLike$class.r(StringLike.scala:255)
    at scala.collection.immutable.StringOps.r(StringOps.scala:29)
    at scala.collection.immutable.StringLike$class.r(StringLike.scala:244)
    at scala.collection.immutable.StringOps.r(StringOps.scala:29)
    at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:102)
    at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:72)
    at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIterator.processNext(Unknown Source)
    at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
    at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$8$$anon$1.hasNext(WholeStageCodegenExec.scala:377)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$SingleDirectoryWriteTask.execute(FileFormatWriter.scala:243)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask$3.apply(FileFormatWriter.scala:190)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spar

3 个答案:

答案 0 :(得分:2)

我认为你应该尝试将正则表达式内联到下面。

这是一个蹩脚的解决方案,您应该能够定义一个常量,可能将它放在全局object或其他东西中。我不知道你在哪里定义这将是一个问题。但请记住spark将代码序列化并在分布式工作程序上运行,因此可能会出现问题。

rdd.map { _ =>
   ...

   body = """<[^>]+>""".r.replaceAllIn(body, " ")    

 }

当我在空字符串上运行.r时,我收到一个非常类似的错误。

val x: String = null 
x.r 
java.lang.NullPointerException
  java.util.regex.Pattern.<init>(Pattern.java:1350)
  java.util.regex.Pattern.compile(Pattern.java:1028)
  scala.util.matching.Regex.<init>(Regex.scala:223)
  scala.collection.immutable.StringLike.r(StringLike.scala:281)
  scala.collection.immutable.StringLike.r$(StringLike.scala:281)
  scala.collection.immutable.StringOps.r(StringOps.scala:29)
  scala.collection.immutable.StringLike.r(StringLike.scala:270)
  scala.collection.immutable.StringLike.r$(StringLike.scala:270)
  scala.collection.immutable.StringOps.r(StringOps.scala:29)

该错误的行号略有不同,我认为是因为scala版本。我在2.12.2。

答案 1 :(得分:0)

感谢Stephen的回答,我找到了为什么我在我的UDF上获得NPE ...我这样做了(在我的案例中找到匹配):

onpaste

答案 2 :(得分:0)

“ <[^>] +>”很棒,但是我的HTML中有一种类型的东西。它由样式名称和大括号之间的参数组成:

<form data-members-form>
    <input data-members-label type="hidden" value="Free" />
    <input data-members-email type="email" required="true" placeholder="jenny.doe@example.com"
        class="w-full appearance-none rounded border shadow p-3 text-grey-dark mr-2 focus:outline-none">
    <button
        class="w-full p-2 mt-5 py-5 bg-primary-600 text-white font-medium rounded hover:bg-primary-800 hover:font-semibold">
        <span class="button-content">Sign Up for Free</span>
        <span class="button-loader text-white">{{> "icons/loader"}}</span>
    </button>
    <div class="form-response-messages">
        <div class="form-success bg-green-300 text-green-800 border-green-900 border rounded-lg my-5 p-5">Awww yeah,
            Success! Please check your email to login.</div>
        <div class="form-error bg-red-300 text-red-800 border-red-900 border rounded-lg my-5 p-5">Oh no! Looks like
            there was an error. Please try again.</div>
    </div>
</form>

我尝试使用以下方法提取它们,但没有用:

form[data-members-form] .form-response-messages {
    display: none;
}

/*-- Show success message on success --*/
form[data-members-form].success .form-response-messages .form-success {
    display: block;
}

/*-- Show error message on error --*/
form[data-members-form].error .form-response-messages .form-error {
    display: block;
}