Python 字符编码
ASCII编码:
计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255,最多只能表示2**8个不同的字符
由于计算机是美国人发明的,因此,最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。全世界有上百种语言,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
Unicode编码:
因此,万国码(Unicode)应运而生。Unicode编码“至少”2个字节即16位,把所有语言都统一到一套编码里,这样就解决了乱码的问题,现代操作系统和大多数编程语言都直接支持Unicode。
UTF-8 :
UTF-8编码可理解为可变长的编码,目的是为了节约存储空间,把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字一般是3个字节。
字符编码的转换
现在计算机系统通用的字符编码工作方式:在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器,所以很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码
unicode=>utf8: encode编码
utf8=>unicode: decode解码
utf8=>unicode=>gbk: utf8转换成gbk需要经过unicode
因为Python的诞生比Unicode标准发布的时间还要早,所以最早的Python只支持ASCII编码,普通的字符串'ABC'在Python内部都是ASCII编码的,Python在后来添加了对Unicode的支持。
Python3.x 的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。
如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes,Python对bytes类型的数据用带b前缀的单引号或双引号表示: x = b'ABC' 虽然b'ABC'和'ABC'内容显示一样,但bytes的每个字符都只占用一个字节。
以Unicode表示的str通过encode()方法或bytes()函数可以编码为指定的bytes (ascii或 utf-8)
>>> 'ABC'.encode('ascii') b'ABC' >>> type(b'ABC') <class 'bytes'> >>> '中文'.encode('utf-8') b'\xe4\xb8\xad\xe6\x96\x87'
>>> bytes('中文','utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法 或 str()
>>> b'ABC'.decode('ascii') 'ABC' >>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8') '中文'
>>> str(b'\xe4\xb8\xad\xe6\x96\x87','utf-8')
'中文
用len()函数计算str的字符数,如果换成bytes,就计算字节数:
>>> len('ABC') 3 >>> len('中文') 2 >>> len(b'ABC') 3 >>> len('中文'.encode('utf-8')) 6
可见,1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。
str和bytes互相转换时,需要指定编码,最常用的编码是UTF-8。Python当然也支持其他编码方式,比如把Unicode编码成GB2312,如果没有特殊业务要求,仅使用UTF-8编码。在操作字符串时,为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。
由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:
#!/usr/bin/env python --告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
# -*- coding: utf-8 -*- --告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
声明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM编码,如果.py文件本身使用UTF-8 编码,并且也申明了# -*- coding: utf-8 -*-,打开命令提示符测试就可以正常显示中文
注:Python3.x 解释器默认按UTF-8编码读取源码,不需要声明