【问题标题】:PySpark — UnicodeEncodeError: 'ascii' codec can't encode characterPySpark — UnicodeEncodeError:“ascii”编解码器无法编码字符
【发布时间】:2017-02-01 09:49:26
【问题描述】:

使用 spark.read.csvencoding='utf-8' 将带有外来字符 (åäö) 的数据帧加载到 Spark 中,并尝试执行简单的 show()。

>>> df.show()

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/spark/python/pyspark/sql/dataframe.py", line 287, in show
print(self._jdf.showString(n, truncate))
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffd' in position 579: ordinal not in range(128)

我认为这可能与 Python 本身有关,但我无法理解 here for example 中提到的任何技巧如何应用于 PySpark 和 show() 函数的上下文中。

【问题讨论】:

  • 你是不是只有在使用show时才会遇到这种情况?
  • @zero323 我可以尝试其他与打印相关的命令吗?
  • 如果df.rdd.map(lambda x: x).count()成功,初学者可以试试。
  • @zero323 – 是的,我什至成功运行了一些 Spark SQL 查询——只有这个 show() 函数在字符串中的字符编码上失败了。
  • 所以rdd.take(20) 例如执行没有问题?如果是这样,问题可能是标题。您是否可以通过一种或另一种方式提供可用于重现问题的最小数据样本?

标签: python python-2.7 apache-spark pyspark


【解决方案1】:

我在使用以下版本的 Spark 和 Python 时遇到了同样的问题:

火花 - 2.4.0

Python - 2.7.5

以上解决方案都不适合我。

对我来说,问题是在尝试将结果 RDD 保存到 HDFS 位置时发生。我从 HDFS 位置获取输入并将其保存到 HDFS 位置。以下是出现此问题时用于读写操作的代码:

读取输入数据:

monthly_input = sc.textFile(monthly_input_location).map(lambda i: i.split("\x01"))
monthly_input_df = sqlContext.createDataFrame(monthly_input, monthly_input_schema)

写入 HDFS:

result = output_df.rdd.map(tuple).map(lambda line: "\x01".join([str(i) for i in line]))
result.saveAsTextFile(output_location)

我把读写代码分别改成如下代码:

阅读代码:

monthly_input = sqlContext.read.format("csv").option('encoding', 'UTF-8').option("header", "true").option("delimiter", "\x01").schema(monthly_input_schema).load(monthly_input_location)

编写代码:

output_df.write.format('csv').option("header", "false").option("delimiter", "\x01").save(output_location)

这不仅解决了问题,还大大提高了 IO 性能(几乎 3 倍)。

但是在使用上面的写逻辑时有一个已知问题,我还没有找到合适的解决方案。如果输出中有空白字段,由于 CSV 编码,它将显示用双引号(“”)括起来的空白值。

对我来说,这个问题目前不是什么大问题。无论如何,我正在将输出加载到配置单元,并且可以在导入自身时删除双引号。

PS:我仍在使用 SQLContext。尚未升级到 SparkSession。但从我目前尝试过的基于 SparkSession 的代码中类似的读写操作也将类似地工作。

【讨论】:

    【解决方案2】:
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    

    这对我有用,我预先设置了编码,它在整个脚本中都有效。

    【讨论】:

    【解决方案3】:

    https://issues.apache.org/jira/browse/SPARK-11772 谈到了这个问题并给出了一个运行的解决方案:

    export PYTHONIOENCODING=utf8
    

    在运行pyspark 之前。我想知道为什么上面的方法有效,因为sys.getdefaultencoding() 为我返回了utf-8,即使没有它。

    How to set sys.stdout encoding in Python 3? 也谈到了这一点,并为 Python 3 提供了以下解决方案:

    import sys
    sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1)
    

    【讨论】:

    • 是的,它正在工作.. 在 spark 提交之前导出它 export PYTHONIOENCODING=utf8
    • 这不再是一个有效的解决方案
    猜你喜欢
    • 2015-10-21
    • 2010-12-11
    • 2012-07-02
    • 2010-12-11
    • 2021-09-28
    • 2016-12-17
    • 2013-04-21
    相关资源
    最近更新 更多