仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1541|回复: 7
打印 上一主题 下一主题

[CentOS(社区)] 带来一篇Python字符编码详解

[复制链接]
飘灵儿 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-14 20:47:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
如果您觉得本篇CentOSLinux教程讲得好,请记得点击右边漂浮的分享程序,把好文章分享给你的好朋友们!1.字符编码简介

1.1.ASCII

ASCII(AmericanStandardCodeforInformationInterchange),是一种单字节的编码。盘算机世界里一开端只要英文,而单字节可以表现256个分歧的字符,可以表现一切的英文字符和很多的掌握符号。不外ASCII只用到了个中的一半(x80以下),这也是MBCS得以完成的基本。
1.2.MBCS

但是盘算机世界里很快就有了其他说话,单字节的ASCII已没法知足需求。后来每一个说话就制订了一套本身的编码,因为单字节能表现的字符太少,并且同时也须要与ASCII编码坚持兼容,所以这些编码纷纭应用了多字节来表现字符,如GBxxxBIGxxx等等,他们的规矩是,假如第一个字节是x80以下,则依然表现ASCII字符;而假如是x80以上,则跟下一个字节一路(共两个字节)表现一个字符,然后跳过下一个字节,持续往下断定。
这里,IBM创造了一个叫CodePage的概念,将这些编码都支出囊中并分派页码,GBK是第936页,也就是CP936。所以,也能够应用CP936表现GBK。
MBCS(Multi-ByteCharacterSet)是这些编码的统称。今朝为止人人都是用了双字节,所以有时刻也叫做DBCS(Double-ByteCharacterSet)。必需明白的是,MBCS并非某一种特定的编码,Windows里依据你设定的区域分歧,MBCS指代分歧的编码,而Linux里没法应用MBCS作为编码。在Windows中你看不到MBCS这几个字符,由于微软为了加倍洋气,应用了ANSI来恫吓人,记事本的另存为对话框里编码ANSI就是MBCS。同时,在简体中文Windows默许的区域设定里,指代GBK。
1.3.Unicode

后来,有人开端认为太多编码招致世界变得过于庞杂了,让人脑壳疼,因而人人坐在一路拍脑壳想出来一个办法:一切说话的字符都用统一种字符集来表现,这就是Unicode。
最后的Unicode尺度UCS-2应用两个字节表现一个字符,所以你经常可以听到Unicode应用两个字节表现一个字符的说法。但过了不久有人认为256*256太少了,照样不敷用,因而涌现了UCS-4尺度,它应用4个字节表现一个字符,不外我们用的最多的依然是UCS-2。
UCS(UnicodeCharacterSet)还仅仅是字符对应码位的一张表罢了,好比"汉"这个字的码位是6C49。字符详细若何传输和贮存则是由UTF(UCSTransformationFormat)来担任。
一开端这事很简略,直接应用UCS的码位来保留,这就是UTF-16,好比,"汉"直接应用x6Cx49保留(UTF-16-BE),或是倒过去应用x49x6C保留(UTF-16-LE)。但用着用着美国人认为本身吃了年夜亏,之前英文字母只须要一个字节就可以保留了,如今年夜锅饭一吃酿成了两个字节,空间消费年夜了一倍……因而UTF-8横空降生。
UTF-8是一种很别扭的编码,详细表示在他是变长的,而且兼容ASCII,ASCII字符应用1字节表现。但是这里省了的一定是从其余处所抠出来的,你确定也据说过UTF-8里中文字符应用3个字节来保留吧?4个字节保留的字符更是在泪奔……(详细UCS-2是怎样酿成UTF-8的请自行搜刮)
别的值得一提的是BOM(ByteOrderMark)。我们在贮存文件时,文件应用的编码并没有保留,翻开时则须要我们记住本来保留时应用的编码并应用这个编码翻开,如许一来就发生了很多费事。(你能够想说记事本翻开文件时并没有让选编码?无妨先翻开记事本再应用文件->翻开看看)而UTF则引入了BOM来表现本身编码,假如一开端读入的几个字节是个中之一,则代表接上去要读取的文字应用的编码是响应的编码:
BOM_UTF8xefxbbxbf
BOM_UTF16_LExffxfe
BOM_UTF16_BExfexff
并非一切的编纂器都邑写入BOM,但即便没有BOM,Unicode照样可以读取的,只是像MBCS的编码一样,须要另行指定详细的编码,不然解码将会掉败。
你能够据说过UTF-8不须要BOM,这类说法是纰谬的,只是绝年夜多半编纂器在没有BOM时都是以UTF-8作为默许编码读取。即便是保留时默许使用ANSI(MBCS)的记事本,在读取文件时也是先应用UTF-8测试编码,假如可以胜利解码,则应用UTF-8解码。记事本这个体扭的做法形成了一个BUG:假如你新建文本文件并输出"姹a"然后应用ANSI(MBCS)保留,再翻开就会酿成"汉a",你无妨尝尝:)
2.Python2.x中的编码成绩

2.1.str和unicode

str和unicode都是basestring的子类。严厉意义上说,str实际上是字节串,它是unicode经由编码后的字节构成的序列。对UTF-8编码的str汉应用len()函数时,成果是3,由于现实上,UTF-8编码的汉==xE6xB1x89。
unicode才是真正意义上的字符串,对字节串str应用准确的字符编码停止解码后取得,而且len(u汉)==1。
再来看看encode()和decode()两个basestring的实例办法,懂得了str和unicode的差别后,这两个办法就不会再混杂了:
  1. #coding:UTF-8u=u汉printrepr(u)#uu6c49s=u.encode(UTF-8)printrepr(s)#xe6xb1x89u2=s.decode(UTF-8)printrepr(u2)#uu6c49#对unicode停止解码是毛病的#s2=u.decode(UTF-8)#异样,对str停止编码也是毛病的#u2=s.encode(UTF-8)
复制代码

须要留意的是,固然对str挪用encode()办法是毛病的,但现实上Python不会抛出异常,而是前往别的一个雷同内容但分歧id的str;对unicode挪用decode()办法也是如许。很不睬解为何不把encode()和decode()分离放在unicode和str中而是都放在basestring中,但既然曾经如许了,我们就当心防止出错吧。
2.2.字符编码声明

源代码文件中,假如有效到非ASCII字符,则须要在文件头部停止字符编码的声明,以下:
  1. #-*-coding:UTF-8-*-
复制代码
现实上Python只检讨#、coding和编码字符串,其他的字符都是为了雅观加上的。别的,Python中可用的字符编码有许多,而且还有很多别号,还不辨别巨细写,好比UTF-8可以写成u8。拜见http://docs.python.org/library/codecs.html#standard-encodings。
别的须要留意的是声明的编码必需与文件现实保留时用的编码分歧,不然很年夜概率会涌现代码解析异常。如今的IDE普通会主动处置这类情形,转变声明后同时换成声明的编码保留,但文本编纂器控们须要当心:)
2.3.读写文件

内置的open()办法翻开文件时,read()读取的是str,读取后须要应用准确的编码格局停止decode()。write()写入时,假如参数是unicode,则须要应用你愿望写入的编码停止encode(),假如是其他编码格局的str,则须要先用该str的编码停止decode(),转成unicode后再应用写入的编码停止encode()。假如直接将unicode作为参数传入write()办法,Python将先应用源代码文件声明的字符编码停止编码然后写入。
  1. #coding:UTF-8f=open(test.txt)s=f.read()f.close()printtype(s)#<typestr>#已知是GBK编码,解码成unicodeu=s.decode(GBK)f=open(test.txt,w)#编码成UTF-8编码的strs=u.encode(UTF-8)f.write(s)f.close()
复制代码

别的,模块codecs供给了一个open()办法,可以指定一个编码翻开文件,应用这个办法翻开的文件读取前往的将是unicode。写入时,如果参数是unicode,则应用open()时指定的编码停止编码后写入;假如是str,则先依据源代码文件声明的字符编码,解码成unicode后再进行前述操作。绝对内置的open()来讲,这个办法比拟不轻易在编码上涌现成绩。
  1. #coding:GBKimportcodecsf=codecs.open(test.txt,encoding=UTF-8)u=f.read()f.close()printtype(u)#<typeunicode>f=codecs.open(test.txt,a,encoding=UTF-8)#写入unicodef.write(u)#写入str,主动停止解码编码操作#GBK编码的strs=汉printrepr(s)#xbaxba#这里会先将GBK编码的str解码为unicode再编码为UTF-8写入f.write(s)f.close()
复制代码

2.4.与编码相干的办法

sys/locale模块中供给了一些获得以后情况下的默许编码的办法。
  1. #coding:gbkimportsysimportlocaledefp(f):print%s.%s():%s%(f.__module__,f.__name__,f())#前往以后体系所应用的默许字符编码p(sys.getdefaultencoding)#前往用于转换Unicode文件名至体系文件名所应用的编码p(sys.getfilesystemencoding)#获得默许的区域设置并前往元祖(说话,编码)p(locale.getdefaultlocale)#前往用户设定的文本数据编码#文档提到thisfunctiononlyreturnsaguessp(locale.getpreferredencoding)#xbaxba是汉的GBK编码#mbcs是不推举应用的编码,这里仅作测试注解为何不该该用printr"xbaxba.decode(mbcs):",repr(xbaxba.decode(mbcs))#在笔者的Windows上的成果(区域设置为中文(简体,中国))#sys.getdefaultencoding():gbk#sys.getfilesystemencoding():mbcs#locale.getdefaultlocale():(zh_CN,cp936)#locale.getpreferredencoding():cp936#xbaxba.decode(mbcs):uu6c49
复制代码

3.一些建议

3.1.应用字符编码声明,而且统一工程中的一切源代码文件应用雷同的字符编码声明。

这点是必定要做到的。
3.2.摈弃str,全体应用unicode。

按引号前先按一下u最后做起来确切很不习气并且常常会忘却再跑归去补,但假如这么做可以削减90%的编码成绩。假如编码困扰不严重,可以不参考此条。
3.3.应用codecs.open()替换内置的open()。

假如编码困扰不严重,可以不参考此条。
3.4.相对须要防止应用的字符编码:MBCS/DBCS和UTF-16。

这里说的MBCS不是指GBK甚么的都不克不及用,而是不要应用Python里名为MBCS的编码,除非法式完整不移植。
Python中编码MBCS与DBCS是同义词,指以后Windows情况中MBCS指代的编码。Linux的Python完成中没有这类编码,所以一旦移植到Linux必定会涌现异常!别的,只需设定的Windows体系区域分歧,MBCS指代的编码也是纷歧样的。分离设定分歧的区域运转2.4末节中的代码的成果:
  1. #中文(简体,中国)#sys.getdefaultencoding():gbk#sys.getfilesystemencoding():mbcs#locale.getdefaultlocale():(zh_CN,cp936)#locale.getpreferredencoding():cp936#xbaxba.decode(mbcs):uu6c49#英语(美国)#sys.getdefaultencoding():UTF-8#sys.getfilesystemencoding():mbcs#locale.getdefaultlocale():(zh_CN,cp1252)#locale.getpreferredencoding():cp1252#xbaxba.decode(mbcs):uxbaxba#德语(德国)#sys.getdefaultencoding():gbk#sys.getfilesystemencoding():mbcs#locale.getdefaultlocale():(zh_CN,cp1252)#locale.getpreferredencoding():cp1252#xbaxba.decode(mbcs):uxbaxba#日语(日本)#sys.getdefaultencoding():gbk#sys.getfilesystemencoding():mbcs#locale.getdefaultlocale():(zh_CN,cp932)#locale.getpreferredencoding():cp932#xbaxba.decode(mbcs):uuff7auff7a
复制代码

可见,更改区域后,应用mbcs解码获得了不准确的成果,所以,当我们须要应用GBK时,应当直接写GBK,不要写成MBCS。
UTF-16同理,固然绝年夜多半操作体系中UTF-16是UTF-16-LE的同义词,但直接写UTF-16-LE只是多写3个字符而已,而万一某个操作体系中UTF-16酿成了UTF-16-BE的同义词,就会有毛病的成果。现实上,UTF-16用的相当少,但用到的时刻照样须要留意。
--END--
原文地址:http://www.ckuyun.com/huxi/archive/2010/12/05/1897271.html
如果您觉得本篇CentOSLinux教程讲得好,请记得点击右边漂浮的分享程序,把好文章分享给你的小伙伴们!
活着的死人 该用户已被删除
沙发
发表于 2015-1-16 23:00:45 | 只看该作者

带来一篇Python字符编码详解

我学习Linux的心得体会,希望对大家的学习有所帮助,由于水平有限,本文难免有所欠缺,望请指正。
admin 该用户已被删除
板凳
发表于 2015-1-25 16:14:28 | 只看该作者
学习Linux,应该怎样学,主要学些什么,一位Linux热心学习者,一段学习Linux的风云经验,历时十二个小时的思考总结,近十位网络Linux学习者权威肯定,为您学习Linux指明方向。
简单生活 该用户已被删除
地板
发表于 2015-2-3 12:09:29 | 只看该作者
甚至目前许多应用软件都是基于它的。可是没有哪一个系统是十分完美的。
乐观 该用户已被删除
5#
发表于 2015-2-8 23:31:58 | 只看该作者
linux鸟哥的私房菜,第三版,基础篇,网上有pdf下的,看它的目录和每章的介绍就行了,这个绝对原创!
只想知道 该用户已被删除
6#
发表于 2015-2-26 14:52:18 | 只看该作者
其中不乏很多IT精英的心血。我们学透以后更可以做成自己的OS!?
深爱那片海 该用户已被删除
7#
发表于 2015-3-8 16:05:40 | 只看该作者
下面笔者在论坛看到的一个好问题: “安装红旗4.0后,系统紫光输入法自带的双拼方案和我的习惯不一样,如何自定义双拼方案解决?谢谢?”这个问题很简练。
第二个灵魂 该用户已被删除
8#
发表于 2015-3-16 09:43:59 | 只看该作者
通过一条缓慢的调制解调器线路,它也能操纵几千公里以外的远程系统。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 04:30

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表