【问题标题】:Turn off force UTF8 encoding in pyspark在 pyspark 中关闭强制 UTF8 编码
【发布时间】:2019-12-16 05:20:10
【问题描述】:

我有一个类似下面的 python 代码来使用 pyspark 从 Oracle 读取数据。

tableDF = spark.read \
            .format("jdbc") \
            .option("driver", "oracle.jdbc.driver.OracleDriver") \
            .option("url", "jdbc:oracle:thin:@" + hostid + ".dev.com:1521/" + databaseinstance) \
            .option("dbtable", sqlstring) \
            .option("numPartitions", 1) \
            .option("fetchsize", fetchsize) \
            .option("user", contextname) \
            .option("password", contextname) \
            .load() \

数据库源字符集是 US7ASCII,但由于没有验证将数据加载到 Oracle 中,它包含具有各种编码字符集的数据。 简而言之,即使 DB 字符集是 US7ASCII,它的列中也包含 UTF8、ISO-8859-1 混合编码的数据。

我能够成功地将数据从 Oracle 读取到数据帧中而没有任何问题,但是由于 pyspark 强制编码为 UTF-8 导致我的一些数据具有 UTF-8 替换字符,例如 EFBFA2EFBE80EFBE93 由于在包含源字符集为 US7ASCII 的列中存在 Unicode 字符 E2 80 93 而无法正确识别

该字段的类型是varchar。存储的值为,即en dash character。返回的是字节 0xE2 0x80 0x93,而不是字符,这些字节被转换为 ???

NAME 值为的行上调用DUMP(NAME,'1016')

CLINIC – NORTH 

返回:

Typ=1 Len=69 CharacterSet=US7ASCII: 43,4f,52,41,20,e2,80,93,20,4e,4f,52,54,48,

因此,我希望简单地从 Oracle 读取数据,而不对我的数据进行任何编码。基本上,我不希望对正在检索的数据进行任何强制编码。我只是想要它们在 Oracle 中的存储方式。

有没有办法通过 pyspark 关闭此默认编码为 UTF-8? 要么 如何使 JDBC 或 PYTHON 驱动程序以任何编码形式处理这些字符?

正如我已经提到的,因为我的数据库包含混合编码字符集,强制任何特定编码(如 UTF8/US-ASCII/ISO-8859-1)适用于某些数据,但不适用于其他数据,这就是为什么我需要一种根本不强制执行任何编码的方法。

任何帮助或指导将不胜感激。谢谢

【问题讨论】:

  • 当您尝试使用错误的代码页读取 non-Unicode 文本时,会出现 Unicode 替换字符。关闭 UTF8 转换不会使问题消失,使用的代码页仍然是错误的。 Oracle 中的文本是如何存储的?什么是类型的列?除非它是 Unicode 类型之一,否则您必须使用正确的代码页来阅读它。
  • 无论如何,Spark 是基于 JVM 构建的,其字符串是 Unicode,特别是 UTF16。问题出在 JDBC 驱动程序本身,而不是 Spark。
  • @PanagiotisKanavos 是的,没错。当存储在 Oracle 中的底层字符不兼容 UTF8 时,转换就会变得混乱。即使 Oracle 中的字符集是 US7ASCII,因为我们在将数据加载到 Oracle 时没有进行任何验证,我们不能保证所有底层数据都是 US7ASCII,因为 oracle 也可以在其列中存储扩展的 ASCII。所以,这里有两种方法,要么我需要正确识别底层编码,要么根本不编码。因为在我的情况下,底层数据可以有任何编码,最好完全不编码
  • 那么,是否有任何配置可以通过 pyspark 传递给 JDBC 驱动程序以避免这种强制编码?
  • 没有强制编码,或者更确切地说,每个 Java/JVM 应用程序,包括 Spark,都使用 Unicode。问题是不正确的字符集。否则,JDBC 驱动程序将正常工作。您必须找出错误发生的位置。检查存储的文本、列排序规则、实际内容。列类型有哪些?可能是文本已经在数据库中损坏了吗?如果 Oracle 驱动程序能够使用正确的代码页转换 varchar 值,这表明文本可能使用错误的代码页存储,则不会有任何问题

标签: python encoding utf-8 pyspark pyspark-sql


【解决方案1】:

我不确定我的想法是否适用于你的情况,但我试过这个:

.option("encoding", "US-ASCII")

这应该会改变编码。


如果您使用例如 pyspark,另一个想法是全局设置编码:

import sys 
reload(sys) #reload seems to be important, otherwise next step can break
sys.setdefaultencoding('us-ascii')

【讨论】:

  • 这首先导致问题。在第 47 条评论的某处,OP 表示数据来自具有 US7ASCII 字符集的表,但包含使用 UTF8 编码存储的 en-Dash。 JDBC 以 US-ASCII 形式返回数据,这意味着 Python 接收三个字符而不是单个 en Dash。本质上,OP 想要的是与问题所问的完全相反。 OP 实际上想强制 JDBC 将 US-ASCII 视为 UTF8
  • 现在我做对了。非常感谢您的解释。 @PanagiotisKanavos
猜你喜欢
  • 2010-09-28
  • 2017-01-08
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 2016-04-08
  • 1970-01-01
相关资源
最近更新 更多