如何跨Python版本读取包含0xEB字符的文件?
解决跨Python版本读取含0xEB字节文件的问题
我之前也踩过这个坑,本质是Python2和Python3对open()函数的默认行为差异在搞事情:
- Python2里
open()默认返回字节流(str类型本质就是字节串),不管文件里是什么字节,直接读出来就行,不会做编码解码操作; - Python3里
open()默认返回文本流,会自动用UTF-8编码去解码字节,而0xEB并不是合法的UTF-8续字节,自然就抛出UnicodeDecodeError了。
下面给你两种靠谱的跨版本解决方案,按需选择:
方案1:读取原始字节(最稳妥)
如果你的需求只是获取文件的原始字节数据,不需要转成文本,直接用二进制模式打开文件就行——这在Python2和3里行为完全一致:
with open("oxeb.txt", "rb") as f: content = f.read()
这样content在Python2里是str(字节串),在Python3里是bytes类型,都能完整保留0xEB这个字节,后续处理字节的逻辑也能跨版本兼容。
方案2:读取为文本(兼容原Python2行为)
如果确实需要把内容当成文本处理,那可以利用Latin-1(ISO-8859-1)编码——它是单字节编码,每个0x00到0xFF的字节都会映射到唯一的Unicode字符,完美匹配Python2里默认读取文本的行为(Python2的str转成Python3的str用Latin-1解码完全对应)。
你可以用io.open来实现跨版本兼容(io模块在Python2.6+就存在,行为和Python3的open一致):
from io import open with open("oxeb.txt", "r", encoding="latin-1") as f: content = f.read()
或者也可以通过版本判断来写:
import sys if sys.version_info >= (3, 0): with open("oxeb.txt", "r", encoding="latin-1") as f: content = f.read() else: with open("oxeb.txt", "r") as f: content = f.read()
这样处理后,在Python3里读取到的文本会把0xEB映射成Unicode字符ë,和Python2里直接读取的str(字节串)转成Unicode的结果完全一致。
总结
- 优先用二进制模式读取,完全避开编码问题,适合处理非文本文件或不需要编码转换的场景;
- 如果需要文本内容,用Latin-1编码可以完美兼容Python2的默认行为,不会出现解码错误。
内容的提问来源于stack exchange,提问作者Ogen
相关产品推荐
相关产品推荐

