科普:Python编码的前世今生
一旦走上了编程之路,如果你不把编码问题搞清楚,那么它将像幽灵一般纠缠你整个职业生涯,各种灵异事件会接踵而来,挥之不去。只有充分发挥程序员死磕到底的精神你才有可能彻底摆脱编码问题带来的烦恼。
我第一次遇到编码问题是写JavaWeb相关的项目,一串字符从浏览器游离到应用程序代码中,翻江倒海沉浸到数据库中,随时随地都有可能踩到编码的地雷。
第二次遇到编码问题就是学Python的时候,在爬取网页数据时,编码问题又出现了,当时我的心情是崩溃的,用时下最ing的一句话就是:“我当时就懵逼了”。
为了搞清字符编码,我们得从计算机的起源开始,计算机中的所有数据,不论是文字、图片、视频、还是音频文件,本质上最终都是按照类似01010101的数字形式存储的。我们是幸运的,我们也是不幸的,幸运的是时代赋予了我们都有机会接触计算机,不幸的是,计算机不是我们国人发明的,所以计算机的标准得按美帝国人的习惯来设计,那么最开始计算机是通过什么样的方式来表现字符的呢?这要从计算机编码的发展史说起。
ASCII
每个做JavaWeb开发的新手都会遇到乱码问题,每个做Python爬虫的新手都会遇到编码问题,为什么编码问题那么蛋疼呢?
这个问题要从1992年Guido van Rossum创造Python这门语言说起,那时的Guido绝对没想到的是Python这门语言在今天会如此受大家欢迎,也不会想到计算机发展速度会如此惊人。Guido在当初设计这门语言时是不需要关心编码的,因为在英语世界里,字符的个数非常有限,26个字母(大小写)、10个数字、标点符号、控制符,也就是键盘上所有的键所对应的字符加起来也不过是一百多个字符而已。这在计算机中用一个字节的存储空间来表示一个字符是绰绰有余的,因为一个字节相当于8个比特位,8个比特位可以表示256个符号。于是聪明的美国人就制定了一套字符编码的标准叫ASCII(American Standard Code for Information Interchange),每个字符都对应唯一的一个数字,比如字符A对应的二进制数值是01000001,对应的十进制就是65。最开始ASCII只定义了128个字符编码,包括96个文字和32个控制符号,一共128个字符,只需要一个字节的7位就能表示所有的字符,因此ASCII只使用了一个字节的后7位,最高位都为0。
EASCII(ISO/8859-1)
然而计算机慢慢地普及到其他西欧地区时,他们发现还有很多西欧所特有的字符是ASCII编码表中没有的,于是后来出现了可扩展的ASCII叫EASCII,顾名思义,它是在ASCII的基础上扩展而来,把原来的7位扩充到8位,它完全兼容ASCII,扩展出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。然而EASCII时代是一个混乱的时代,大家没有统一标准,他们各自把最高位按照自己的标准实现了自己的一套字符编码标准,比较著名的就有 CP437,CP437是Windows系统中使用的字符编码,如下图:
cp437
另外一种被广泛使用的EASCII还有 ISO/8859-1(Latin-1),它是国际标准化组织(ISO)及国际电工委员会(IEC)联合制定的一系列8位元字符集的标准,ISO/8859-1只继承了CP437字符编码的128-159之间的字符,所以它是从160开始定义的,不幸的是这些众多的ASCII扩充字集之间互不兼容。
iso8859-1
GBK
随着时代的进步,计算机开始普及到千家万户,比尔盖茨让每个人桌面都有一台电脑的梦想得以实现。但是计算机进入中国不得不面临的一个问题就是字符编码,虽然咱们国家的汉字是人类使用频率最多的文字,汉字博大精深,常见的汉字就有成千上万,这已经大大超出了ASCII编码所能表示的字符范围了,即使是EASCII也显得杯水车薪,于是聪明的中国人自己弄了一套编码叫 GB2312,又称GB0,1981由中国国家标准总局发布。GB2312编码共收录了6763个汉字,同时它还兼容ASCII。GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。不过GB2312还是不能100%满足中国汉字的需求,对一些罕见的字和繁体字GB2312没法处理,后来就在GB2312的基础上创建了一种叫GBK的编码。GBK不仅收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。同样GBK也是兼容ASCII编码的,对于英文字符用1个字节来表示,汉字用两个字节来标识。
Unicode
对于如何处理中国人自己的文字我们可以另立山头,按照我们自己的需求制定一套编码规范,但是计算机不止是美国人和中国人用啊,还有欧洲、亚洲其他国家的文字诸如日文、韩文全世界各地的文字加起来估计也有好几十万,这已经大大超出了ASCII码甚至GBK所能表示的范围了,况且人家为什么用采用你GBK标准呢?如此庞大的字符库究竟用什么方式来表示好呢?于是统一联盟国际组织提出了Unicode编码,Unicode的学名是“Universal Multiple-Octet Coded Character Set”,简称为UCS。
Unicode有两种格式:UCS-2和UCS-4。UCS-2就是用两个字节编码,一共16个比特位,这样理论上最多可以表示65536个字符,不过要表示全世界所有的字符显然65536个数字还远远不够,因为光汉字就有近10万个,因此Unicode 4.0规范定义了一组附加的字符编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)。
Unicode理论上完全可以涵盖一切语言所用的符号。世界上任何一个字符都可以用一个Unicode编码来表示,一旦字符的Unicode编码确定下来后,就不会再改变了。但是Unicode有一定的局限性,一个Unicode字符在网络上传输或者最终存储起来的时候,并不见得每个字符都需要两个字节,比如一字符“A“,用一个字节就可以表示的字符,偏偏还要用两个字节,显然太浪费空间了。第二问题是,一个Unicode字符保存到计算机里面时就是一串01数字,那么计算机怎么知道一个2字节的Unicode字符是表示一个2字节的字符呢,还是表示两个1字节的字符呢,如果你不事先告诉计算机,那么计算机也会懵逼了。Unicode只是规定如何编码,并没有规定如何传输、保存这个编码。例如“汉”字的Unicode编码是 6C49,我可以用4个 ASCII 数字来传输、保存这个编码;也可以用UTF-8编码的3个连续的字节 E6 B1 89来表示它。关键在于通信双方都要认可。因此Unicode编码有不同的实现方式,比如:UTF-8、UTF-16等等。这里的Unicode就像英语一样,做为国与国之间交流世界通用的标准,每个国家有自己的语言,他们把标准的英文文档翻译成自己国家的文字,这是实现方式,就像UTF-8。
UTF-8
UTF-8(Unicode Transformation Format)作为Unicode的一种实现方式,广泛应用于互联网,它是一种变长的字符编码,可以根据具体情况用1-4个字节来表示一个字符。比如英文字符这些原本就可以用ASCII码表示的字符用UTF-8表示时就只需要一个字节的空间,和ASCII是一样的。对于多字节(n个字节)的字符,第一个字节的前n为都设为1,第n+1位设为0,后面字节的前两位都设为10。剩下的二进制位全部用该字符的UNICODE码填充。
以汉字“好”为例,“好”对应的Unicode是 597D,对应的区间是 0000 0800--0000 FFFF,因此它用UTF-8表示时需要用3个字节来存储,597D 用二进制表示是: 0101100101111101,填充到 1110xxxx 10xxxxxx 10xxxxxx 得到11100101 10100101 10111101,转换成16进制:E5A5BD,因此“好”的Unicode“597D”对应的UTF-8编码是“E5A5BD”。
中文 好 unicode 0101 100101 111101 编码规则 1110xxxx 10xxxxxx 10xxxxxx -------------------------- utf-8 11100101 10100101 10111101 -------------------------- 16进制utf-8 e 5 a 5 b d
Python字符编码
注:以下代码和概念都是基于Python 2.x。
现在总算把理论说完了。再来说说Python中的编码问题。Python的诞生时间比Unicode要早很多,Python的默认编码是ASCII。
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
所以在Python源代码文件中如果不显式地指定编码的话,将出现语法错误
#test.py
print "你好"
上面是test.py脚本,运行 python test.py 就会包如下错误:
File “test.py”, line 1 yntaxError: Non-ASCII character ‘\xe4′ in file test.py on line 1, but
no encoding declared; see http://www.python.org/ ps/pep-0263.html for details
为了在源代码中支持非ASCII字符,必须在源文件的第一行或者第二行显示地指定编码格式:
# coding=utf-8
或者是:
#!/usr/bin/python
# -*- coding: utf-8 -*-
在Python中和字符串相关的数据类型,分别是 str、unicode 两种,他们都是 basestring 的子类,可见str与unicode是两种不同类型的字符串对象。
basestring
/ \
/ \
str unicode
对于同一个汉字“好”,用str表示时,它对应的就是UTF-8编码'\xe5\xa5\xbd',而用 Unicode表示时,它对应的符号就是 u'\u597d',与u"好"是等同的。需要补充一点的是,str类型的字符其具体的编码格式是UTF-8还是GBK,还是其它格式,根据操作系统相关。比如在Windows系统中,cmd命令行中显示的:
# windows终端
>>> a = '好'
>>> type(a)
# linux终端
>>> a='好'
>>> type(a)
<type 'unicode'>
encode
版权说明:本文"科普:Python编码的前世今生"内容来源于互联网用户投稿,该文观点仅代表作者本人。本站不拥有所有权,不承担相关法律责任。如发现有涉嫌侵权/违法违规的内容,请发送邮件至2855532207QQ邮箱申诉,一经查实,本站将立刻处理。
-
目录网站的发展历程
- 目录网站是一种非常古老的互联网工具,它可以帮助用户快速找到他们需要的网站。在互联网的早期,目录网站是非常重要的,因为当时网站数量还不多,而且大多数人对互联网还不熟悉。下面我们来看一下目录网站的发展历程。
-
推荐一些优秀的网站目录
- 在互联网的世界里,有成千上万的网站等待着你去探索。但是,有时候在如此多的选择中找到自己需要的网站并不是一件容易的事情。因此,我们在这里向您推荐一些优秀的网站目录,这些目录可以帮助您快速找到自己需要的网站。
-
互联网推广从33目录网开始
- 【互联网推广从33目录网开始】33分类目录网汇聚国内外优秀的网站网址,并免费提供网站收录/分类目录/网站推广/网站导航服务,快速帮助中小企业提升网站排名及知名度。
-
如何开启hsts网站安全功能
- 【如何开启hsts网站安全功能】HSTS的出现,在带来安全、便捷的同时,咱们也需要谨慎操作,因为如果某个参数设置不当,就有可能将导致网站长时间无法访问,那损失就大了。
-
给B2B和B2C营销策划人的建议
- 给B2B和B2C营销策划人的建议:在买家购买商品的每一个阶段,B2B和B2C之间都存在不同,很多人都分不清B2B跟B2C的区别,但是B2B的销售额几乎是B2C的两倍,B2C来源于B2B。B2B品牌在创造和构建围绕有助于最终购买决策的人类购买者和影响者的故事方面呈现出更多B2C特征。相反,B2C品牌更注重建立信任和信誉。
-
自媒体对互联网发展的深度影响
- 【自媒体对互联网发展的深度影响】自媒体又称“公民媒体”或“个人媒体”,是指私人化、平民化、普泛化、自主化的传播者,以现代化、电子化的手段,向不特定的大多数或者特定的单个人传递规范性及非规范性信息的新媒体的总称。
-
未来5年UI设计师的发展前景
- 【未来5年UI设计师的发展前景】一般来说,根据设计师的经验和技术,UI设计师可以分为初级设计师、高级设计师、资深设计师和首席设计师,但是今天我们要说的是UI设计师的发展方向。UI设计行业随着移动互联网快速发展,出现人求需求井喷,而薪资水平也是在不断的提升,对UI设计师的技术水平也提出了更高的要求。UI设计是指对软件的人机交互、操作逻辑、界面美观的整体设计。