最近使用python-spark遇到一个无法解决的中文编码问题。
查了网上的资料和解决方法,都无法使之解决。
不知道哪位大佬可以帮忙指点一二?
问题摘要,python使用UTF8编码,spark使用的是ascii编码,处理中文文件时遇到乱码问题。
情形1、读取本地文件创建DataFrame时的中文编码问题
#in python
import codecs
local_file = "a_local_file.csv"
cate_list = []
for line in open(local_file, "r"):
line = line.strip()
line = line.replace(codecs.BOM_UTF8, "")
arr = line.split(',')
if len(arr) < 3:
continue
else:
tier2_name = arr[0]
tier3_name = arr[1]
tier3_code = int(arr[2])
cate_list.append((tier3_code, tier3_name, tier2_name))
df_cate = spark.createDataFrame(cate_list,
["third_cate_code","third_cate_name","second_cate_name"])
df_cate.cache()
df_cate.createOrReplaceTempView("cate_codes")
df_cate.show()
show的结果:【如显示,中文全是乱码!!!】
情形2: spark自定义函数UDF时的中文乱码问题
第一步:定义并注册两个UDF,将code转成其中文名称
#in python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time: 2021/04/19 20:20 上午
# @Author: gao
#pyspark
import os, sys, datetime, time
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
def regist_bin_udf(spark):
#将配置文件读入并获取配置信息
import codecs
local_file = "a_local_file.csv"
data_dict = {}
for line in open(local_file, "r"):
line = line.strip()
line = line.replace(codecs.BOM_UTF8,"")
arr = line.split(',')
if len(arr) < 3:
continue
else:
tier2_name = arr[0]
tier3_name = arr[1]
tier3_code = int(arr[2])
data_dict[tier3_code] = {}
data_dict[tier3_code]["tier2_name"] = tier2_name
data_dict[tier3_code]["tier3_name"] = tier3_name
#写UDF获取二级类目的名称
def tier2_name(tier3):
if tier3 in data_dict.keys():
name = data_dict[int(tier3)]["tier2_name"]
else:
name = 'NaN'
return name
spark.udf.register("tier2_name",tier2_name)
# 写UDF获取三级类目的名称
def tier3_name(tier3):
if tier3 in data_dict.keys():
name = data_dict[int(tier3)]["tier3_name"]
else:
name = 'NaN'
return name
spark.udf.register("tier3_name", tier3_name)
第二步:调用UDF,获取中文名称
#in python
sql_string = """
SELECT
encode(decode(tier3_name(third_cate_code),'utf-8'), 'ascii') as third_cate_name,
tier2_name(third_cate_code) as second_cate_name,
FROM
your_table_name
WHERE
dt = '{day_begin}'
AND third_cate_code IN {third_cate_codes}
""".format(day_begin=day_begin,third_cate_codes=third_cate_codes)
sys.stderr.write(sql_string)
spark.sql(sql_string)
第三步:查看结果 【中文名称都是乱码!!!】
3、尝试过的方法
尝试过以下方法,然而并没有卵用~!!!
3.1 声明utf-8编码
reload(sys)
sys.setdefaultencoding('utf-8')
3.2 情形一中读取本地文件时,使用.decode("utf-8").encode("ascii")重新编码
#in python
tier2_name = arr[0].encode("ascii")
tier3_name = arr[1].decode("utf-8").encode("ascii")
3.3 情形二中读取本地文件,定义UDF时,使用.decode("utf-8").encode("ascii")重新编码
改动的代码同3.2
3.4 情形二中spark.sql时,使用encode(decode(,),) 重新编码
select
encode(decode(tier3_name(third_cate_code),'utf-8'), 'ascii') as third_cate_name,
tier2_name(third_cate_code) as second_cate_name
from
...