python3中打开文件必须显式指定encoding参数,否则读写中文易出unicodedecodeerror;文本模式默认处理换行和编解码,二进制模式需加b且不可用encoding;r+/w+/a+等混合模式仍需注意编码匹配与光标位置。

Python3 中打开文件必须显式指定编码,否则读写中文大概率出错;open() 默认文本模式,二进制模式必须加 b 标志,且不能混用 encoding 参数。
Python3 的 open() 必须带 encoding 才能安全读写文本
Python2 的 open() 默认按系统编码(通常是 ASCII 或 GBK)读取,不报错但容易静默乱码;Python3 则强制要求显式声明 encoding,否则在读取含非 ASCII 字符的文件时会抛出 UnicodeDecodeError。
- 正确写法(Python3):
with open('data.txt', 'r', encoding='utf-8') as f: - 错误写法(Python3):
with open('data.txt', 'r') as f:—— 若文件含中文,运行时大概率崩溃 - Python2 中等效写法是
f.read().decode('utf-8'),但这是事后补救,不是打开时的编码约定
r、w、a 等模式默认是文本模式,加 b 才切到二进制模式
文本模式和二进制模式本质行为不同:文本模式自动处理换行符(\n ↔ \r\n)、执行编码/解码;二进制模式原样读写字节,不碰编码,也不改换行符。
- 文本模式示例:
open('log.txt', 'w')→ 写入'hello\n'在 Windows 上实际落盘为b'hello\r\n' - 二进制模式示例:
open('image.png', 'rb')→ 返回bytes,不能传字符串,也不能指定encoding - 混用会报错:
open('x.txt', 'wb', encoding='utf-8')→ 直接触发ValueError: binary mode doesn't take an encoding argument
r+、w+、a+ 模式在 Python3 中仍需注意编码与光标位置
这些“读写混合模式”在 Python3 中依然存在,但因默认文本模式+强制编码,行为比 Python2 更严格。尤其当文件内容编码与指定 encoding 不一致时,read() 可能提前失败,后续 write() 也可能因光标位置错乱写偏。
-
w+会清空文件,即使你只打算读 —— 这点和 Python2 完全一致,但 Python3 下清空后若立即read()得到空字符串,不是 bug -
r+要求文件必须存在,且写入时从当前位置开始覆盖,不会自动追加;若想“读完再写末尾”,得手动f.seek(0, 2) - 跨平台写入时,避免用
r+直接修改 UTF-8 文件中的某一行 —— 中文字符占多字节,覆盖可能截断字节流,导致后续解码失败
为什么 Python2 能“蒙混过关”,而 Python3 不行?
根本原因是 Python2 把字符串当作字节序列(str),对编码不做假设;Python3 明确区分 str(Unicode 文本)和 bytes(原始字节),open() 在文本模式下必须在两者之间架起转换桥梁,而桥的参数(即 encoding)不能缺省。
- Python2 中
open('x.txt').read()返回str(其实是 bytes),你爱怎么 decode 就怎么 decode - Python3 中
open('x.txt').read()返回str(Unicode),它必须从 bytes 解码而来,没encoding就不知道怎么解 - 这个设计让乱码从“运行时不可见”变成“启动就报错”,看似麻烦,实则堵住了大量隐蔽数据污染问题
最常被忽略的一点:即使你只读纯英文配置文件,只要文件里有 BOM(比如 Windows 记事本保存的 UTF-8 with BOM),Python3 用 encoding='utf-8' 也能正常读,但用 encoding='utf-8-sig' 才能自动剥离 BOM —— 这个细节不查文档几乎没人主动写。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











