一文搞懂Python字符编码问题,值得收藏

要说在整个编程领域中最难的问题有哪些的话,字符编码的问题,也就是乱码问题,绝对算得上很多程序员写代码时的一个“噩梦” 。以至于在IT界有个著名的笑话,“手持一把锟斤拷,口中直呼烫烫烫”,如果你笑了,那么你肯定是做IT的,哈哈哈 。而在Python这门语言中,因为python2和python3本身编码机制完全不一样,所以这个问题又尤其突出 。包括我本人在内,也被这个编码问题困扰了很久,一直没有完全搞明白 。后来,为了彻底解决编码问题,专门查询了很多的书籍和资料,终于搞清楚了关于编码问题的来龙去脉以及各种情况下存在的问题以及解决方式,今天这篇文章就来做一个总结,相信大家只要认真看了之后,妈妈再也不会担心你的编码问题了 。
要彻底弄清楚乱码是怎么来的,有两个大的关键因素必须要了解:一个是究竟有哪些编码类型,各种类型有哪些不同的特点,这些必须烂熟于心 。二是你的代码运行环境是什么 。比如是在命令行运行?还是在编辑器中运行?在python2中还是在python3中?在linux系统里面?还是在windows系统里面?弄清楚这两个问题,乱码问题便会迎刃而解 。接下来我们来一一解决这些问题 。
一、编码类型
很多人想不明白为什么计算机中有这么多乱七八糟各种各样的编码,比如什么ASCII啊,GBK,GB2312,UNICODE,UTF8,这些都是什么鬼?为什么要有这么多不同的编码格式?要想搞清楚这些编码问题,必须先了解一下关于字符编码的历史,这些都是祖上留下来的“孽债” 。
1. 什么是字符编码
首先我们来了解下究竟什么是字符编码,为什么要有字符编码这个东西出现?原因很简单,计算机从本质上来说只认识二进制中的0和1,可以说任何数据在计算机中实际的物理表现形式也就是0和1,如果你将硬盘拆开,你是看不到所谓的数字0和1的,你能看到的只是一块光滑闪亮的磁盘,如果你用足够大的放大镜你就能看到磁盘的表面有着无数的凹凸不平的元件,凹下去的代表0,突出的代表1,我们用bit(位)来表示每个这种二进制的数,这就是计算机用来表现二进制的方式 。而我们在处理数据时,一般并不是按位来进行处理,而是按照字节(byte)来进行处理的,一个字节byte=8bit 。那现在我们面临了第一个问题:如何让人类语言能够被计算机正确理解呢?我们以英文为例(因为计算机是美国佬发明的,所以最开始当然只考虑英文的情况),英文中有英文字母(大小写)、标点符号、特殊符号 。如果我们将这些字母与符号给予固定的编号,然后将这些编号转变为二进制用字节来表示,那么计算机明显就能够正确读取这些符号,同时通过这些编号,计算机也能够将二进制转化为编号对应的字符再显示给人类去阅读 。所以,基于这种思想,便产生了ASCII码 。
2. ASCII编码
ASCII码是人类计算机历史上最早发明的字符集,大家都知道 ,计算机是美国佬发明的,他们只用英文,所以可以说ASCII码是专门为表示英文、数字以及英文标点符号而生 。由于英文本身比较简单,就是由26个字母组成,加上0-9十个数字以及一些英文的标点符号 。而在计算机中,1byte=8bit,也就是说有从0000000-11111111共2的8次方共256种不同的组合,这些组合已经足够存储所有的这些英文字母、数字以及标点了,所以早期的编码只有ASCII编码 。
3. GB2312以及其他编码
如果全世界的人都使用英文的话,今天我们就不必这么费神来研究编码问题了 。正因为全世界的语言太多,大家都想使用自己熟悉的语言来使用计算机,比如中国人用计算机当然使用中文了 。那么问题来了,在中文中光常用的汉字就已经达到了6000多个了,很明显之前的ASCII码已经完全无法满足汉字存储的需求了 。怎么办?既然使用ASCII码这样一个字节无法搞定,那么我们自然想到能不能多用1个字节是不能就能搞定了呢?所以,为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为GB码,或国标码 。其中最有影响的是于1980年发布的《信息交换用汉字编码字符集 基本集》,标准号为GB 2312-1980,因其使用非常普遍,也常被通称为国标码 。GB2312编码通行于我国内地;新加坡等地也采用此编码 。几乎所有的中文系统和国际化的软件都支持GB 2312 。所以,大家可以理解为,GB系列的编码是为了适应复杂的中文编码而对ASCII码的一种扩充 。
4. UNICODE标准编码
既然咱们中国人能够对ASCII码进行扩充,以便于显示更复杂的中文,那么其他国家呢?比如日本、韩国,其实也面临着同样的问题 。所以,他们自然也会对ASCII码扩展出自己的一套编码 。假设每种语言都自己搞一套,工作量上去了不说,还为不同编码之间的转换和显示造成了巨大的困难,这也行不通啊 。所以,为了简化不同编码之间的显示和转换问题,很有必要搞一套统一的编码格式出来 。基于这种情况一种新的编码诞生了:Unicode 。Unicode又被称为统一码、万国码;它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求 。Unicode支持欧洲、非洲、中东、亚洲(包括统一标准的东亚象形汉字和韩国表音文字) 。这样不管你使用的是英文或者中文,日语或者韩语,在Unicode编码中都有收录,且对应唯一的二进制编码 。这样大家都开心了,只要大家都用Unicode编码,那就不存在这些转码的问题了,什么样的字符都能够解析了 。


推荐阅读