那些关于字符的编码历史就不细说了,百度随便搜字符编码历史就可以了解非常详细的知识。总结起来就是
计算机刚开始是美国人发明的,他们发明了 asicc 编码,用来编制英文字符,但是随着计算机普及,网络发展壮大,每个国家陆陆续续发明了自己的编码,如 gb2312 等,但是问题来了,这么多编码不兼容啊。于是一个组织搞了一个 Unicode编码,号称可以处理世界上所有的字符,其实无非就是用多字节来编码。然而这样在网络上传输起来很费劲,于是有了 utf-8,utf-16 等具体实现,它们可以很好地解决传输问题。
Python 的编码问题由来已久,搞清这个问题也相当不易。(ps:未来切换到 Python 3,也许这个问题容易搞明白一点)
Python 2 内置编码是 ascii 的,因为 Python 发明时那会还没有 Unicode这货呢,所以,问题一大堆。来看个例子:
# Windows 平台
>>>s = "我爱中国abc"
>>> s.encode('utf-8')
Traceback (most recent call last):
File "", line 1, in
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)
原因是虽然 Python 2 是用 ascii 编码的,但是 WIndows 这货在中国是用 gb2312 来编码的,当进行 encode 的时候,Python 首先会将其转换为 Unicode,然后以 utf-8 的形式具体编码。
ascii 编码为 gb2312 当然会出错了。
# 首先以 gb2312 格式进行解码为 Unicode,
>>> s.decode('gb2312').encode('utf-8')
'\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\xad\xe5\x9b\xbdabc'
# 注意 decode 里面的内容表示以哪种格式进行解码,最后统一解码为 Unicode。
# Python 2 的 unicode 类型就可以直接编码了
>>> s = u'我爱中国abc'
>>> s.encode('utf-8')
b'\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\xad\xe5\x9b\xbdabc'
在 Python 3 里,就没这么多规矩了
Python 3.6.4
>>> s = '我爱中国abc'
>>> s.encode('utf-8')
b'\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\xad\xe5\x9b\xbdabc'
>>>
在 Linux 下进行同样的操作,和 Windows 差不多:
# Ubuntu
>>> s = '我爱中国abc'
>>> s.encode('utf-8')
Traceback (most recent call last):
File "", line 1, in
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
>>>
>>> s.decode('utf-8').encode('utf-8')
'\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\xad\xe5\x9b\xbdabc'
注意在进行 s.encode('utf-8') 的时候,一定要保证 s 是 Unicode 格式的字符串,否则就要进行 decode 解码操作。
查看平台上 Python 的默认编码:
# Python 2
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
# Python 3
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
如果想帮助自己记住 .decode() 和 .encode() 的区别,可
以把字节序列想成晦涩难懂的机器磁芯转储,把 Unicode 字符串想成“人类可读”的文本。那么,把字节序列变成人类可读的文本字符串就是解码,而把字符串变成用于存储或传输的字节序列就是编码。