使用spark.read.csv
使用encoding='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() - 函数的上下文中应用。
答案 0 :(得分:15)
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)
答案 1 :(得分:0)
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
这对我有用,我预先设置了编码,并且在整个脚本中都有效。
答案 2 :(得分:0)
在以下版本的Spark和Python中,我遇到了相同的问题:
SPARK-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的代码中的类似读写操作也将类似地工作。