目录
一些编码知识
编码
指从字符到二进制数据的映射过程
GB2312
收录了大部分中文字符(6763个汉字),兼容 ASCII
GBK
在 GB2312 基础上收录了藏文、蒙文、维吾尔文等主要的少数民族文字
英文字符用 1 个字节,汉字用 2 个字节。
Unicode
计算机怎么知道一个 2 字节的 Unicode 字符是表示一个 2 字节的字符,还是两个 1 字节的字符呢?
Unicode 只是规定如何编码,并没有规定如何传输、保存编码。UTF-9、UTF-16 是 Unicode 编码的实现方式。
UTF-8
是一种变长的编码,可以用 1 - 4 字节,英文字符用 1 个字节。
对于多个(n)字节的字符,第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,后面字节的前两位都设为 10,剩下的二进制位全部用该字符的 Unicode 码填充。
以汉字“好”为例,“好”的 Unicode 编码是 597D,对应的区间是 0000 0800 - 0000 FFFF,所以用 UTF-8 表示时需要 3 个字节。
597D 的二进制表示是:101 1001 0111 1101,按照以上规则填充到 1110xxxx 10xxxxxx 10xxxxxx 中,就是 11100101 10100101 10111101,转为十六进制:E5A5BD。
以下是常见的汉字字符集编码:
GB2312编码:1981年5月1日发布的简体中文汉字编码国家标准。GB2312对汉字采用双字节编码,收录7445个图形字符,其中包括6763个汉字。
BIG5编码:台湾地区繁体中文标准字符集,采用双字节编码,共收录13053个中文字,1984年实施。
GBK编码:1995年12月发布的汉字编码国家标准,是对GB2312编码的扩充,对汉字采用双字节编码。GBK字符集共收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。
GB18030编码:2000年3月17日发布的汉字编码国家标准,是对GBK编码的扩充,覆盖中文、日文、朝鲜语和中国少数民族文字,其中收录27484个汉字。GB18030字符集采用单字节、双字节和四字节三种方式对字符编码。兼容GBK和GB2312字符集。
UNICODE编码:国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。
|
- 获取默认编码的方法
Python IDLE:
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
Windows 10:
C:\Users\fhj>chcp
活动代码页: 936
Linux:
fhj@baron:~$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
python2 编码格式
- 字符串对象
和字符串相关的数据类型(字符串对象):str、unicode。
str 和 unicode 都是 basestring 的子类。basestring是抽象类,所以不能被调用和实例化,但是可以用来判断一个对象是否为str或unicode的实例:
isinstance(obj, basestring)等价于isinstance(obj, (str, unicode))
Windows下:
>>> s = "好"
>>> type(s)
<type 'str'>
>>> s
'\xba\xc3'
>>> s = u"好"
>>> type(s)
<type 'unicode'>
>>> s
u'\u597d'
Linux下:
>>> s = "好"
>>> type(s)
<type 'str'>
>>> s
'\xe5\xa5\xbd'
>>> s = u"好"
>>> type(s)
<type 'unicode'>
>>> s
u'\u597d'
u"好" 表示"好"的 unicode 编码,不同平台下 unicode 类型的字符串存的都是 unicode 编码,是一样的;
而 str 类型的字符串编码格式是 GBK、UTF-8 还是其它格式,和操作系统的默认编码有关。如上,在 Windows 下是 '\xba\xc3',这是 GBK 格式,在 Linux 下,是 '\xe5\xa5\xbd',这是 UTF-8。
- str 和 unicode 的相互转换
>>> s = "好"
>>> u = u"好"
>>> s.decode("gbk")
u'\u597d'
>>> s.decode("gb2312")
u'\u597d'
>>> u.encode("utf-8")
'\xe5\xa5\xbd'
>>>
>>> u.encode("gbk")
'\xba\xc3'
- str() 和 unicode()
str(u) 等价于 u.encode("ascii"),将 unicode 字符串转换成 ascii 字符串。
unicode(s) 等价于 s.decode("ascii"),将 ascii 字符串转换成 unicode 字符串。
所以,str(u)、unicode(s) 都不能对包含非 ascii 字符的字符串进行转换,会报类似如下的错误:
>>> u = u"好"
>>> s = "好"
>>> str(u)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u597d' in position 0: ordinal not in range(128)
>>> unicode(s)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# UnicodeDecodeError: 'ascii' codec can't decode byte 0xba in position 0: ordinal not in range(128)
指定正确的编码就可以解决这个问题:
1、用 u.encode("gbk") 代替 str(u)
2、用 s.decode("gbk") 代替 unicode(s)
>>> u.encode('gbk')
'\xba\xc3'
>>> s.decode('gbk')
u'\u597d'
- 一个 str 字符串对象,其中存的是 unicode 形式的字符串,要将这个 str 转成真正的 unicode 字符串对象,可使用 s.decode('unicode-escape'):
>>> st = 'id\u6211\u662f001'
>>> u = st.decode('unicode-escape')
>>> type(u)
<type 'unicode'>
>>> u
u'id\u6211\u662f001'
>>>
>>> g = u.encode('gbk')
>>> type(g)
<type 'str'>
>>> g
'id\xce\xd2\xca\xc7001'
python3 编码格式
- str
Python3 中:没有 unicode 类型,str 的编码格式为 unicode,等于 Python2 的unicode 类型。
>>> s = "中文"
>>> type(s)
<class 'str'>
>>> s
'中文'
- bytes
bytes 表示二进制字节序列,对 str 进行编码后得到 bytes;反之,对 bytes 解码后得到 str。
>>> b = b"0123aa"
>>> type(b)
<class 'bytes'>
>>> b2 = b"\xff\xabd\x38\x12"
>>> b2
b'\xff\xabd8\x12'
>>> len(b2)
5
- python2 与 python3 字节与字符的对应关系
python2 | python3 | 表现 | 转换方法 | 作用 |
str | bytes | 字节 | decode | 存储 |
unicode | str | 字符 | encode | 显示 |
- str 和 bytes 的相互转换
str转 bytes(encode):
>>> s.encode('gbk')
b'\xd6\xd0\xce\xc4'
>>> type(s.encode('gbk'))
<class 'bytes'>
>>> s.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> s.encode()
b'\xe4\xb8\xad\xe6\x96\x87'
bytes 转 str(decode):
>>> b.decode()
'0123aa'
>>> b.decode('gbk')
'0123aa'
>>> s = "中文"
>>> s
'中文'
>>> s.encode("gbk")
b'\xd6\xd0\xce\xc4'
>>>
>>> b'\xd6\xd0\xce\xc4'.decode('gbk')
'中文'
- str() 和 bytes()
str(b, encoding=’gbk’):把 bytes 转成 str,同时指定转换前 bytes 的编码格式为 gbk,等同于b.decode(‘gbk’)。
>>> b = b'\xd6\xd0\xce\xc4'
>>> str(b, encoding='gbk')
'中文'
>>> s = "中文"
>>> bytes(s, encoding='utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> bytes(s, encoding='gbk')
b'\xd6\xd0\xce\xc4'
bytes(s, encoding=’gbk’):把 str 转成 gbk 编码的 bytes,等同于s.encode(‘gbk’)。
Python2 & Python3 差异
- 解释器对代码的处理
Python2 默认编码是 ASCII,必须在文件头声明 coding 为 utf-8 或者 gbk 后才能有中文字符,Python2 解释器以文件头声明的编码去解释代码,并加载到内存中,也就是说内存中的编码格式和文件编码格式是一样的。所以当 coding 为 utf-8 时,中文打印出来是乱码,为 gbk 时打印出来不会变乱码。
Python3 默认编码是 unicode,Python3 解释器会以文件头声明的编码去解释代码,在加载到内存中之前会先转成 unicode,所以当 coding 为 utf-8 时,打印中文也不会乱码。
- bytes 类型
Python 2 将 str 处理为原生的 bytes 类型,而不是 unicode,可以认为 str 等于 bytes:
>>> isinstance('abc123', str)
True
>>> isinstance('abc123', bytes)
True
Python 3 所有的 str 均是 unicode 类型。