在 python 中使用字符串的时候,尤其是使用中文字符串的时候,常常需要使用到字符串的编解码,而且由于 python2 和 python3 二者对于字符串的实现上略有区别,导致从 python2 切换到 python3,或者需要满足同时支持 python2 和 python3 的时候,对于中文字符串的处理需要尤其注意,一不小心就会导致异常。
首先,在 python 字符串的处理过程中,需要了解三个概念:
- 字符串,类型为 str
- unicode,是一种通用的字符串表示,不属于 ascii/utf8 等,它一般只存在于内存中
- bytes,是将 unicode 具像化之后,使用某一种具体的编码方式(如ascii/utf8)等编码之后的二进制形式,一般保存文本文件的时候,需要明确
而 python2 和 python3 关于编码方式的不同,很大程度上就是因为它们两个对于上面三个概念的实现不同,当然还有一点是它们使用的默认编码方式也不同,先看代码:
# python2
>>> a = '测试'
>>> a
'\xe6\xb5\x8b\xe8\xaf\x95'
>>> b = a.encode()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
>>> c = a.decode()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
>>> d = a.decode('utf-8')
>>> d
u'\u6d4b\u8bd5'
#python3
>>> a = '测试'
>>> a
'测试'
>>> b = a.encode()
>>> b
b'\xe6\xb5\x8b\xe8\xaf\x95'
>>> c = a.decode()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'
从上面两个可以看出,由于 a 是一个中文字符,不属于 ascii 的范围,所以在 python2 中不论是 encode 还是 decode 都会报错,这是因为这两个函数的默认编码方式就是默认的编码方式,但是可以通过 decode(‘utf-8’) 进行 utf8 的解码,成为 unicode 字符。而 encode 函数对于 str 类型来说,本质上就是执行了 str.decode().encode(),所以无论把 str encode 成什么编码的格式的,都会报错。
同时也可以看出,在 python2 和 python3 种,它们对于 str 的理解是不同的,这是因为在 python2 种,str 就是以二进制形式存在的,所以它会与 python3 中的 b 一致。而在 python3 中,以 str 为中介,encode 会将其转换成二进制形式,而 decode 会将二进制形式转变为 str,之所以在 python2 中 str 两个函数都可以调用,那是因为 python2 中的 str 就是以二进制形式存在的,所以它的 decode 可以理解为它作为二进制形式的 decode。