Python2下unicode、utf-8、decode、encode之间的关系。
我感觉我在这方面的认识还不够清晰,希望大牛们能帮帮忙,谢谢!!
回复内容:
py2的编码其实是最最贴近实际的编码形式了。反倒是py3,如果遇到个编码标记错误之类的问题,直接让你自杀……先说编码是什么:我们知道计算机里存储任何数据都是存储的二进制,但是一串文字若是当图片那样存储太浪费空间不说,也会难以解析,所以ascii标准码使用了7位二进制标记了128个字符和控制符号。当然7位不利于数据对齐,所以干脆以8位存储,最高位补个0就好,正好一个字节,此即为基础ascii编码。
但是这128个字符里,虽然包含了常见英文符号和必须的控制符号(比如换行、回车、EOLN、EOF),却对使用其它语言的用户而言没法用,毕竟各家字符不同哇……
首先是欧系拉丁语系指出,既然一个字节一个字符,只用到7位,那么还有128个编号可以用,于是规定了相应的拉丁语系主要符号,同样单字节表示,这样就用到了多出来的一位,这套编码称之为latin-1
再往后,大多数其他拼音语言的国家表示,我们不用拉丁文符号,那么把那128个额外字符改成别的符号,映射自己的文字就没问题了。于是出现了多编码页,也就是最初的codepage。
但是中日韩为首的字形语言系的国家不行啊,你们丫的就几十个符号,可中文之类光常用字就好几千啊……于是针对中文出现了codepage936/gb2312,通过两个字节表示一个汉字,其中包含数千常用字,并且规定最高位为0的部分完全兼容ascii,但是若最高位为1,则必须是两个字节连续出现,用以表示一个汉字——随后还出现了GBK,规定的字符更多,兼容gb2312,同样是个双字节纪录。
然而有两件事情形成了阻碍:一是中文博大精深,汉字实在太多,算上生僻字,两个字节其实也不够用;另一方面,在GB系编码下,所有双字节字符都会被解释成汉字,因此最多做到英汉混排,多语言没戏,同时还会影响到诸如网络传输等等场景,因为同样的双字节二进制数据,对应GBK中文与对应的日文韩文显然不同,这就必须带着编码类型跑,稍不注意就不知道是个啥语言的玩意。
于是出现了unicode,是ANSI标准下的多国语言文字编码。unicode使用32位二进制表示每一个字符,且任意语言任意符号都有独立编码,这样就可以做到使用一套编码同时处理多种不同语言。
unicode是个编码方式,只涉及编号,并不管传输和存储。针对需求,unicode产生了若干传输用编码,其中比较普及的有utf32,utf16和utf8。utf32是每字符32位固定编码,完整映射unicode原编码而不做改变(当然,规定了一下传输时的端序问题);utf16则是最少16位最多32位,属于变长unicode传输方案,以实现对部分codepage的兼容;而utf-8则是最小8位最大32位的编码,变长,且英文部分完全兼容ascii。由于省空间及ascii兼容这两点,使得改用utf8代价最小,才成为了主流。
python2里,与编码有关的有三个部分:
一是源代码识别问题。原本python解释器纯粹把源码使用ascii编码进行解析生成语法树。考虑到源码里可能存在其他语言的字符串量,提供了setdefaultencode接口,但是非常容易引发各类问题。PEP263指出在文件第一行或者第二行(仅限第一行为Unix脚本标注的情况下)写入特殊格式的注释# coding:xxx可以指定解释器解释源码时使用的字符编码。
第二部分则是内置类型转换:python2里的str类,其实是个不存储编码信息的类型。也就是说它把内容二进制按照逐个字节来处理和比对、运算。str类型的「字符串」如果拿来迭代一下,会直接拆成一个个字节来处理。但是,一旦我们需要对非单字节编码的单个字进行处理的时候,python只提供了一个类型来解决问题,即unicode类(注意,实质上py里这个类是utf8进行内存存储的,并不是utf32/unicode原编码),所以常常需要相互转换,将用到encode/decode两个方法。原则上是,decode方法是将一个str按照指定编码解析后转换为unicode,encode方法则是把一个unicode对象用指定编码表示并存储到一个str对象里。
第三点是输入输出。Python2的print的实质是将str里的东西输出到PIPE,如果你print的是一个unicode对象,它会自动根据LOCALE环境变量进行encode之后变成str再输出。然而一般在Windows上都没有设置locale环境变量,py2就按照默认的ascii编码进行处理,于是对中文自然就编码错误了。解决方法是手动encode成对应的输出端可接受的编码后输出。win下一般都是gbk,linux下一般都是utf8
py3中的str则是unicode,bytes才类似于原str,默认代码解析用utf8,默认输出编码也是utf8。
ASCII 、unicode 是字符集,utf-8是字符集的编码方式。
utf-8 是 unicode 字符集一种编码方式。
如果你不指定py文件的编码方式,程序默认按照 ASCII 字符集来解码。所以需要声明文件编码方式。
decode 和 encode
In [1]: a='你好'
In [2]: a
Out[2]: '\xe4\xbd\xa0\xe5\xa5\xbd'
In [3]: b=a.decode('utf-8')
In [4]: b
Out[4]: u'\u4f60\u597d'
In [5]: type(b)
Out[5]: unicode
In [6]: type(a)
Out[6]: str
In [7]: c=b.encode('utf-8')
In [8]: c
Out[8]: '\xe4\xbd\xa0\xe5\xa5\xbd'
In [9]: c==a
Out[9]: True
善于搜索,参考廖雪峰的博客:字符串和编码
这个你搜网上很多啊。 unicode是codepoint 就是一个抽象的\uxxx 代表一个字符。 而utf-8是unicode的一种,用x个字节表示一个抽象的codepoint \uxxx. 所以utf-8是实际的字节串,而unicode是抽象. 你可以把抽象的unicode encode(编码)成utf-8. 也可以把实际的utf-8 解码回unicode. 说了这么多,然并ruan...
请搜索“将python2中汉字会出现乱码的事一次性说清楚”看看! 用 python3 吧,最近用 python, 已经被2.x 的编码问题搞的要怀疑人生了,真是坑死人。。 http://nedbatchelder.com/text/unipain.html
这篇文章不错~
![Web大前端开发直播班](http://m.sbmmt.com/img/upload/aroundimg/000/000/071/626117def31a9203.png)
相关文章推荐
• 详细介绍Python之Pandas知识点• Python数据类型详解之字符串、数字• Python归纳总结之json标准库• 详细讲解Python之Seaborn(数据可视化)• 完全掌握Python数学相关模块独孤九贱(3)_JavaScript视频教程
javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。没有它,你的前端生涯是不完整的。《php.cn独孤九贱(3)-JavaScript视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了javascript知识。
JavaScript教程122663次播放
独孤九贱(6)_jQuery视频教程
jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。 核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等,是全球最流行的前端开发框架之一。PHP中文网根据最新版本,独家录制jQuery最新视频教程,回馈PHP中文网的新老用户。
jQuery教程101259次播放
jQuery与Ajax基础与实战
jQuery是最流行的JS函数库,封装了许多实用的功能,其中最引人入胜的就是Ajax。 jQuery中的Ajax操作,语法简单,操作方便,使Ajax从未如此轻松,前端人员从此不再为与服务器异步交互而发愁,本套课程,精选了最常用的几个方法,从基本的语法到每个参数,再到具体实例进行了全面的讲解。
AJAX教程3128次播放
Git教程(60分钟全程无废话版)
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持
JavaScript教程2415次播放