订阅更新

ETL脚本报UnicodeDecodeError——Python编码问题

Python手册 第 13 题 约 3 分钟读完

本文目录
  1. 先说结论
  2. str vs bytes
  3. 常见编码
  4. 大数据编码解决方案
  5. 实战踩坑:海外多语言编码地狱
  6. 面试高频追问
  7. 总结

先说结论

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-83字节互联网标准99%新项目
GBK2字节中文标准老系统/Windows
Latin-11字节西欧欧洲系统

大数据编码解决方案

# 指定编码
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年大数据老兵,只讲大数据面试干货

刷题进度保存在当前浏览器