在进行文件读写I/O时,或者处理爬虫获取的数据时,又或者处理网络传输的数据时,经常遇到一些类似编码出错的情况,很是烦人。
with open('test.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line)
#运行后出错:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa3 in position 6: invalid start byte
事实上,对于显示,无论数据处理过程中用bytes还是str,也无论编码是用utf-8还是gbk,最终都是转成unicode后打印到屏幕的。
对于存储,无论数据处理过程中用bytes还是str,也无论编码是用utf-8还是gbk,最终都是转成bytes保存的。
显示过程:
- 当显示文本时,显示器需要将字节序列转换成图像。
- 显示器首先会将字节序列转换成 Unicode 字符。
- 然后,显示器会根据 Unicode 字符的编码,找到对应的字形。
- 最后,显示器会将字形显示在屏幕上。
底层是bytes,顶层是unicode 。bytes<----转换---->unicode 之间的转换规则有ascii、utf-8、gbk、unicode等,相同内容,采用不同编码规则,最终得到的文件大小是不一样的,相差可能一倍甚至以上。
对于存储,要转成bytes这个好理解。但为什么数据处理的时候,有些场景使用bytes,有些场景使用str呢?
使用二进制来处理的场景:网络通信:
最主要是网络通信和文件IO操作等场景,bytes相关的api效率更高、api更丰富、数据量更小。
使用str来处理的场景:纯字符串简单运算
直观、简单
s="汉字"
s1=b'\xe6\xb1\x89\xe5\xad\x97'
print('s:',type(s))
print('s.encode():',type(s.encode()))
print('s1:',type(s1))
print('s.encode()==s1',s.encode()==s1)
# s: <class 'str'>
# s.encode(): <class 'bytes'>
# s1: <class 'bytes'>
# s.encode()==s1: True