令人头疼的Python编码问题
前言
你是否在编写Python代码时,老是遇到UnicodeDecodeError/UnicodeEncodeError错误,无从下手。或者是打印一串字符串,确是乱码,搞人心态。
别慌,本文将从编码的前世今生讲解,让你对编码有个深刻了解,以便后期对Python编码问题进行分析和解决。
字符编码的前世今生
大家都知道,电脑本身是不认识字符的,只认识0和1。所以说,电脑的字符需要通过转换为0和1才能被电脑所识别,其实,让字符转换为被电脑识别的01数字的过程,就是字符编码。
当然,字符编码需要定义一套标准,不然电脑就没法准确识别字符了。标准这东西大家都懂的,大部分都是国外先定标准,国内再定,而且很难做到统一。
基于英文的ASCII码,由一个字节表示,一个字节就是8bit,顾名思义就是最大能代表256个字符(2的8次方)。256个字符对付英文绰绰有余,但是中国文字这么多,显然 ASCII码就不适用了。中国人定制了GBK,但是每个国家都自己定制,那就很难统一。
这时候万国码Unicode编码出现,采用了两个字节进行编码,那现在问题也来,就是英文字母一个字节就能搞定,现在都要两个字节,那不是很浪费内存吗。可变长度编码UTF-8出现,解决了这个问题,字母就用一个字节,复杂的字符就用两个字节。
总结下,Unicode编码占用空间,但运行速度快,UTF-8恰恰相反,所以内存中用Unicode编码,而存储用UTF-8,这个大家要好好记着。
Python3编码
首先,Python3默认编码为utf-8。
import sys
print(sys.getdefaultencoding())
# utf-8
然后,Python分为str和bytes两种数据类型,文本字符为str,str能表示Unicode 字符集中所有字符,bytes代表二进制数据。
a = 'a'
b = '罗攀'
print(type(a),type(b))
c = b'\xe7\xbd\x97\xe6\x94\x80'
print(c,type(c))
#<class 'str'> <class 'str'>
#b'\xe7\xbd\x97\xe6\x94\x80' <class 'bytes'>
encode 与 decode
之前的错误分为UnicodeDecodeError和UnicodeEncodeError,其实就是编码和解码错误。
简单的说,从字符转为电脑能识别的01,就是编码,01转换为字符,就是解码。这里的编码和解码必须一致,不然就会报错。
str 与 bytes 之间的转换就是用 encode 和从decode 方法。
a = '罗攀'
print(a.encode('utf-8'))
print(a.encode('utf-8').decode('utf-8'))
print(a.encode('gb2312').decode('utf-8'))
# b'\xe7\xbd\x97\xe6\x94\x80'
#罗攀
#Traceback (most recent call last):
# File "/Users/luopan/Python练习/编码问题.py", line 25, in #<module>
# print(a.encode('gb2312').decode('utf-8'))
#UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc2 in position 0: invalid continuation byte
案例分析
例如,我在本地新建一个txt,编码为utf-16。
如果我们直接读取文件,就会报错,那是因为python默认编码为utf-8。
所以我们需要指定编码即可。
我们下期再见~