python中str与bytes混用易引发unicodedecodeerror,需明确区分文本(open(..., encoding='utf-8'))与二进制(open(..., 'rb'))操作;处理bom应使用'utf-8-sig'编码自动剥离。

Python 中 str 和 bytes 混用导致 UnicodeDecodeError
Python 3 默认字符串是 Unicode,但只要一碰文件、网络或 C 扩展,就容易掉进编码陷阱。最常见的是读文件时没指定 encoding,或者把 bytes 直接和 str 拼接。
- 错误现象:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0—— 典型二进制当文本读了 - 真实场景:用
open('data.bin', 'r')读图片、PDF 或旧数据库导出的二进制 dump - 正确做法:明确区分用途 —— 文本走
open(..., encoding='utf-8'),二进制走open(..., 'rb') - 注意:
sys.stdin和subprocess输出也默认按系统 locale 解码,跨环境易崩;建议显式用locale.getpreferredencoding()或强制utf-8
处理含 BOM 的 UTF-8 文件时 strip() 失效
BOM(ufeff)在 UTF-8 中虽不必要,但 Windows 记事本、某些 Excel 导出仍会加。它不是空白字符,strip() 删不掉,常导致字段比对失败或 JSON 解析报错。
- 错误现象:
json.loads(line)报Expecting value,但肉眼看不出开头有空格 - 检查方法:打印
repr(line[:10]),看到'\ufeff{...'就是 BOM - 解决方式:读文件时用
encoding='utf-8-sig'(Python 自动剥离 BOM),别自己replace('ufeff', '') - 兼容性注意:
utf-8-sig对无 BOM 文件完全透明,但旧版 Python(io.TextIOWrapper 有细微差异,生产环境建议统一用open(..., encoding='utf-8-sig')
正则匹配中文、Emoji 等宽字符时 re.match() 行为异常
re 默认不识别 Unicode 字符属性,w 只匹配 ASCII 字母数字,. 在 re.DOTALL 下也不匹配换行以外的控制字符 —— 更别说 Emoji 了。
- 错误现象:
re.match(r'^w+$', '你好')返回None;re.split(r's+', 'a??b')把 Emoji 当空白切开 - 必须加
flags=re.UNICODE(Python 3 默认已启用,但显式写上更安全) - 真正管用的是 Unicode 属性:用
p{Han}?不行,Pythonre不支持;改用regex模块(pip install regex),它支持p{Script=Han}、p{Emoji} - 性能提醒:
regex比re慢 10–20%,高频简单匹配(如邮箱校验)别换
用 json.dumps() 输出中文时变成 uXXXX
这是 Python 默认行为,不是 bug。但 API 返回、日志打印、调试时全是一堆 u 编码,可读性差,还可能被下游误解析。
立即学习“Python免费学习笔记(深入)”;
- 根本原因:
json.dumps()默认ensure_ascii=True,所有非 ASCII 字符转义 - 修复很简单:
json.dumps(data, ensure_ascii=False)—— 但得确认下游能正确接收 UTF-8 字节流 - 关键坑:
json.dumps(..., ensure_ascii=False)输出的是str,如果写入文件且没设encoding='utf-8',可能触发UnicodeEncodeError - Web 场景额外注意:HTTP 响应头要带
Content-Type: application/json; charset=utf-8,否则浏览器可能乱码










