本篇内容主要讲解“python编码的原理及使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python编码的原理及使用”吧!
编码就是为了解决字符和字节之间的关系。
分字符和字节是为了解决人机之间的关系,一般人只能读字符,机器只能识别字节。
字符'a',人能够识别,机器不能识别,机器只能识别字节。
所以需要一种把字符'a'转换为字节的技术。
这种技术就是编码,例如我们最常见的ASCII(American Standard Code for Information Interchange)码,就包含英文字符数字和一些控制字符。
我们通过ASCII码表就可以找到字符'a'对应的数字为97,这样我们就可以把字符'a'通过编码转换为二进制字节01100001,这样机器就能识别了。
我们一般说的编码,指字符集和字符集中字符对应的值,而不是编码方式
一般的编码方式就是字符集中字符的编码对应的二进制
Unicode字符集有所不同,有多种常用的编码方式,后面详细介绍。
因为有不同的人,使用了不同的字符,如中国人使用了中文字符,正如你现在读到的字符一样,我们在ASCII码表中是找不到对应字符的,自然也不能根据ASCII把字符转换为字节。
所以我们自己就需要新的编码方式,来包含我们自己的字符,从最开始的GB2312到GBK,再到GB18030。
同理,其他语言也有自己对应的字符集和编码。
在国际化的进程中,只玩自己的编码肯定是不行的,所以需要统一的编码,就是包含世界字符,这样只需要在应用中使用Unicode码,就能避免为应用做适配。
我们知道编码是包含字符集和字符集中字符对应的值,一般字符集和对应的值放在一起做为一个对应编码的码表。
Unicode有2个字符集,UCS-2和UCS-4,因为UCS-4兼容UCS-2,所以这里介绍一下UCS-4。
UCS-4使用4字节编码,最高位都是0,所以最高字节的8位有7位有效位。
UCS-4使用最高字节的7位来标识组(group),也就是有2^7=128个组。
UCS-4使用次高字节来标识平面(plane),8位共2^8=256个平面。
UCS-4使用第3字节来标识行(row),8位2^8=256行。
UCS-4使用第4字节来标识码位(cell),同理有256个码位。
group 0的plane 0被称作Basic Multilingual Plane(BMP)
UCS-4中,高两个字节为0的码位被称作BMP,BMP去掉2个全为0的高字节之后,就是2字节的UCS-2。
通过上面的介绍我们很容易算出:UCS-2共有2^16=65536个码位。
这也是在python2.x中:
import sys print sys.maxunicode
打印的值是65535的原因(从0开始,所以最大码位是65535)。
Unicode计划使用了17个平面,每个平面65536个码位,共有17×65536=1114112个码位。
这也是在python3.x中:
import sys print sys.maxunicode
打印的值是1114111的原因
先介绍一下'中文'这2个字符的相关编码:
'中文'的Unicode编码:\u4e2d\u6587 '中文'的UTF-8编码:\xe4\xb8\xad\xe6\x96\x87 '中文'的GBK编码:\xd6\xd0\xce\xc4
下面代码不是通过交互程序,而是写入文件,在cmd执行。
print("中文")
加入有文件名为test-encoding.py的文件内容如上所示,我们在中文环境windows下执行该文件,就会得到下面的错误。
我们可以通过查看test-encoding.py文件的16进制,可以看出test-encoding.py文件使用的是UTF-8编码,对比'中文'的编码得出。
我们也可以看出这不是一个执行时候的错误,因为这是一个SyntaxError,说明是一个语法错误。
同时这个错误也告诉了我们原因,是因为有非ASCII字符,因为python默认的编码是ASCII,所以不能包含有非ASCII字符。
需要包含非ASCII字符我们需要一点特殊的处理,就是告诉python解释器,文件使用的编码方式。
# -*- coding: utf-8 -*- print("中文")
添加的注释部分是告诉python解释器使用utf-8方式做为字符与字节之间的编码方式。
告诉解释器使用utf-8编码就够了吗?
显然不是,因为还涉及到其他的编码方式,例如我们在cmd中执行上面的文件,会得到输出
涓枃
上面的输出值其实就是'中文'这2个字符的UTF-8编码\xe4\xb8\xad\xe6\x96\x87对应的GBK编码。 可以自己对照GBK码表检查,也可以使用在线转换编码工具转换验证。
因为windows默认的代码页是936,也就是GBK编码。
可以通过下面的2中方式解决:
# -*- coding: utf-8 -*- print(u"中文") print(a.decode('utf-8').encode('gbk'))
python2.x默认的编码是ASCII python3.x默认的编码是UTF-8
可以通过sys.getdefaultencoding()查看默认编码方式
那么默认的编码方式到底是什么?
在有些风骚的操作中,可能会教你使用下面的方式解决乱码:
# -*- coding: utf-8 -*- import sys print(sys.getdefaultencoding()) reload(sys) sys.setdefaultencoding('utf-8') print(sys.getdefaultencoding()) a = '中文' print(a)
然而这并没有什么用,因为这是输出端的问题
那这个骚操作在什么地方有用呢?
答案是处理unicode的时候:
# -*- coding: utf-8 -*- import sys print(sys.getdefaultencoding()) # reload(sys) # sys.setdefaultencoding('utf-8') with open(r'F:\tmp\test.txt', 'w') as f: f.write('测试') f.write(u'测试')
执行上面的代码,会得到下面的错误(2.x):
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
但是把注释代码取消注释,就没有问题了。
我们来分析一下: f.write(str)接收的是一个str类型的参数,u'测试'是一个unicode类型。
unicode到str需要encode,字节和字符之间的转换是需要编码的,显然这里使用的是:
u'测试'.encode(sys.getdefaultencoding())
python 交互式使用的编码默认会读取系统的编码,中文环境下windows下一般是GBK。
所以我们使用交互式的方式一般是没有乱码的问题。
UnicodeEncodeError: 'gbk' codec can't encode character u'\xa0' in position 392477: illegal multibyte sequence
有时候会遇到上面的错误,出现这个错误的原因基本都是因为有输出到cmd的命令,也就是基本是因为print('xxx')造成的,其中xxx是GBK不兼容的字符。
其实我们可以很容易的构造一个类似的错误出来(2.x):
print('龦'.decode("utf-8")) #print('龦'.decode("utf-8").encode("gbk"))
在中文环境下的windows命令行执行包含上面代码的文件就会看到UnicodeEncodeError错误。
Unicode编码中: 基本汉字范围:4E00-9FA5(20902个) 基本汉字补充:9FA6-9FEF(74个) 龦的Unicode码是:9FA6,GBK中是没有包含龦这个字的
解决办法: 出现这个错误,就说明包含有超出GBK范围的字符了,所以就不要使用GBK编码方式了。
中文windows命令行默认GBK,不修改代码页肯定有这个问题,只有修改代码页才能解决。
换种思路直接输出到文件,使用UTF-8编码不是挺好的。
#a是字符串(str)类型 a = '中文' #b是unicode类型 b = u'中文'
2者的不同之处在于:
str类型使用的是系统默认编码(可设置)
unicode的类型使用的是unicode的编码
转换: str通过decode可以获取到unicode类型 unicode的通过encode得到str类型
2.x默认使用的是ASCII做字符与字节之间的编码转换,使用的字符集是UCS-2。
因为2.x没有byte类型,所以不同编码之间要转换先存储为unicode编码,然后需要什么编码,再从unicode编码转换为对应的编码。
相比于2.x,3.x版本就正常多了,和其他语言的逻辑保持了一致性。
首先最重要的是添加了byte类型,即字节类型。
不再显示的使用unicode编码,而是遵从:
字符<--->编码<--->字节
#字符--->编码--->字节 bs = "中文".encode('utf-8') #字节--->编码--->字符 ch = bs.decode("utf-8")
3.x默认使用utf-8做字节和字符之间转换的编码方式,使用的字符集是UCS-4。
乱码说明字节-->字符的编码出问题了。
所以首先得弄清楚文件、网络中的字节使用的是什么编码方式,是ASCII、GBK、UTF-8……
然后得弄清楚输出字符的终端、编辑器是什么编码,然后对应起来: decode、encode配对使用一样的编码就可以了。
有些朋友可能会说,这不是废话吗?我知道是什么编码,还会乱码?
问题的重点在于:字节从哪里来,显示字符的编辑器或终端使用什么编码。这样至少可以定位大多数问题。
至于中间经过多次转换的,那就需要仔细排查了。
到此,相信大家对“python编码的原理及使用”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。