ETL脚本报UnicodeDecodeError——Python编码问题
先说结论
str是Unicode字符串,bytes是字节序列,encode/decode互转。最佳实践:① 统一UTF-8;② 读外部数据明确指定编码;③ 处理不了用errors='replace'跳过。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
str vs bytes
s = '你好'
b = s.encode('utf-8') # b'\xe4\xbd\xa0\xe5\xa5\xbd'
b = s.encode('gbk') # b'\xc4\xe3\xba\xc3'
# 同一文字不同编码字节完全不同
# 用错编码解码 = 乱码或UnicodeDecodeError
b'\xe4\xbd\xa0'.decode('gbk') # 乱码!
常见编码
| 编码 | 中文字节数 | 特点 | 场景 |
|---|---|---|---|
| UTF-8 | 3字节 | 互联网标准 | 99%新项目 |
| GBK | 2字节 | 中文标准 | 老系统/Windows |
| Latin-1 | 1字节 | 西欧 | 欧洲系统 |
大数据编码解决方案
# 指定编码
df = pd.read_csv('data.csv', encoding='gbk')
# 不知道编码?自动检测
import chardet
with open('data.csv','rb') as f:
print(chardet.detect(f.read(10000)))
# 兜底:无法解码的字符替换为?
df = pd.read_csv('data.csv', encoding='utf-8', errors='replace')
# PySpark
spark.read.csv('data.csv', encoding='GBK', header=True)
实战踩坑:海外多语言编码地狱
某短剧出海公司,99%API返回UTF-8,但一个欧洲平台返回Latin-1。ETL统一UTF-8解码,处理到欧洲数据时崩了。
解决:① 检查HTTP Content-Type charset;② chardet自动检测;③ errors='replace'兜底。宁可丢几个字符也不让脚本崩。
面试高频追问
追问一:UTF-8和Unicode关系?
Unicode是字符集(给每个字符编号),UTF-8是编码方式(码点转字节)。Python 3的str存Unicode码点,encode转UTF-8字节。
追问二:BOM是什么?
文件开头的编码标记。UTF-8 BOM是EF BB BF。Windows记事本默认加BOM。Python用encoding='utf-8-sig'自动跳过。
追问三:Python 2和3字符串区别?
Python 2的str是bytes,unicode才是字符串。Python 3把str改成Unicode。这是2到3最大的不兼容改动。
总结
编码面试讲三层:① str vs bytes(encode/decode互转);② 常见编码(UTF-8标准、GBK中文老系统、chardet检测);③ 大数据处理(read_csv指定encoding、errors='replace'兜底、多源数据不假设编码)。
下一篇聊正则表达式:解析日志比split快5倍。
你们遇到过编码问题吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,只讲大数据面试干货