python脚本python 编码问题题

python 中文乱码问题深入分析
字体:[ ] 类型:转载 时间:
一直以来,python中的中文编码就是一个极为头大的问题,经常抛出编码转换的异常,python中的str和unicode到底是一个什么东西呢?
在本文中,以'哈'来解释作示例解释所有的问题,“哈”的各种编码如下: 1. UNICODE (UTF8-16),C854; 2. UTF-8,E59388; 3. GBK,B9FE。 一、python中的str和unicode 一直以来,python中的中文编码就是一个极为头大的问题,经常抛出编码转换的异常,python中的str和unicode到底是一个什么东西呢? 在python中提到unicode,一般指的是unicode对象,例如'哈哈'的unicode对象为 u'\u54c8\u54c8' 而str,是一个字节数组,这个字节数组表示的是对unicode对象编码(可以是utf-8、gbk、cp936、GB2312)后的存储的格式。这里它仅仅是一个字节流,没有其它的含义,如果你想使这个字节流显示的内容有意义,就必须用正确的编码格式,解码显示。 例如:
对于unicode对象哈哈进行编码,编码成一个utf-8编码的str-s_utf8,s_utf8就是是一个字节数组,存放的就是'\xe5\x93\x88\xe5\x93\x88',但是这仅仅是一个字节数组,如果你想将它通过print语句输出成哈哈,那你就失望了,为什么呢?
因为print语句它的实现是将要输出的内容传送了操作系统,操作系统会根据系统的编码对输入的字节流进行编码,这就解释了为什么utf-8格式的字符串“哈哈”,输出的是“鍝堝搱”,因为 '\xe5\x93\x88\xe5\x93\x88'用GB2312去解释,其显示的出来就是“鍝堝搱”。这里再强调一下,str记录的是字节数组,只是某种编码的存储格式,至于输出到文件或是打印出来是什么格式,完全取决于其解码的编码将它解码成什么样子。
这里再对print进行一点补充说明:当将一个unicode对象传给print时,在内部会将该unicode对象进行一次转换,转换成本地的默认编码(这仅是个人猜测)
二、str和unicode对象的转换
str和unicode对象的转换,通过encode和decode实现,具体使用如下:
将GBK'哈哈'转换成unicode,然后再转换成UTF8
三、Setdefaultencoding
如上图的演示代码所示:
当把s(gbk字符串)直接编码成utf-8的时候,将抛出异常,但是通过调用如下代码:
import&sys
reload(sys)
sys.setdefaultencoding('gbk')
后就可以转换成功,为什么呢?在python中str和unicode在编码和解码过程中,如果将一个str直接编码成另一种编码,会先把str解码成unicode,采用的编码为默认编码,一般默认编码是anscii,所以在上面示例代码中第一次转换的时候会出错,当设定当前默认编码为'gbk'后,就不会出错了。
至于reload(sys)是因为Python2.5&初始化后会删除&sys.setdefaultencoding&这个方法,我们需要重新载入。
四、操作不同文件的编码格式的文件
建立一个文件test.txt,文件格式用ANSI,内容为:
用python来读取
# coding=gbk
print open("Test.txt").read()
结果:abc中文
把文件格式改成UTF-8:
结果:abc涓?枃
显然,这里需要解码:
# coding=gbk
import codecs
print open("Test.txt").read().decode("utf-8")
结果:abc中文
上面的test.txt我是用Editplus来编辑的,但当我用Windows自带的记事本编辑并存成UTF-8格式时,
运行时报错:
Traceback (most recent call last):
File "ChineseTest.py", line 3, in&
print open("Test.txt").read().decode("utf-8")
UnicodeEncodeError: 'gbk' codec can't encode character u'\ufeff' in position 0: illegal multibyte sequence
原来,某些软件,如notepad,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。
因此我们在读取时需要自己去掉这些字符,python中的codecs module定义了这个常量:
# coding=gbk
import codecs
data = open("Test.txt").read()
if data[:3] == codecs.BOM_UTF8:
data = data[3:]
print data.decode("utf-8")
结果:abc中文
五、文件的编码格式和编码声明的作用
源文件的编码格式对字符串的声明有什么作用呢?这个问题困扰一直困扰了我好久,现在终于有点眉目了,文件的编码格式决定了在该源文件中声明的字符串的编码格式,例如:
str&=&'哈哈'
print&repr(str)
a.如果文件格式为utf-8,则str的值为:'\xe5\x93\x88\xe5\x93\x88'(哈哈的utf-8编码)
b.如果文件格式为gbk,则str的值为:'\xb9\xfe\xb9\xfe'(哈哈的gbk编码)
在第一节已经说过,python中的字符串,只是一个字节数组,所以当把a情况的str输出到gbk编码的控制台时,就将显示为乱码:鍝堝搱;而当把b情况下的str输出utf-8编码的控制台时,也将显示乱码的问题,是什么也没有,也许'\xb9\xfe\xb9\xfe'用utf-8解码显示,就是空白吧。&_&
说完文件格式,现在来谈谈编码声明的作用吧,每个文件在最上面的地方,都会用#&coding=gbk&类似的语句声明一下编码,但是这个声明到底有什么用呢?到止前为止,我觉得它的作用也就是三个:
声明源文件中将出现非ascii编码,通常也就是中文;
在高级的IDE中,IDE会将你的文件格式保存成你指定编码格式。
决定源码中类似于u'哈'这类声明的将‘哈'解码成unicode所用的编码格式,也是一个比较容易让人迷惑的地方,看示例:
#coding:gbk
ss&=&u'哈哈'
print&repr(ss)
print&'ss:%s'&%&ss
将这个些代码保存成一个utf-8文本,运行,你认为会输出什么呢?大家第一感觉肯定输出的肯定是:
u'\u54c8\u54c8'
但是实际上输出是:
u'\u935d\u581d\u6431'
为什么会这样,这时候,就是编码声明在作怪了,在运行ss&=&u'哈哈'的时候,整个过程可以分为以下几步:
1)&获取'哈哈'的编码:由文件编码格式确定,为'\xe5\x93\x88\xe5\x93\x88'(哈哈的utf-8编码形式)
2)&转成 unicode编码的时候,在这个转换的过程中,对于'\xe5\x93\x88\xe5\x93\x88'的解码,不是用utf-8解码,而是用声明编码处指定的编码GBK,将'\xe5\x93\x88\xe5\x93\x88'按GBK解码,得到就是''鍝堝搱'',这三个字的unicode编码就是u'\u935d\u581d\u6431',至止可以解释为什么print&repr(ss)输出的是u'\u935d\u581d\u6431' 了。
好了,这里有点绕,我们来分析下一个示例:
#-*-&coding:utf-8&-*-
ss&=&u'哈哈'
print&repr(ss)
print&'ss:%s'&%&ss
将这个示例这次保存成GBK编码形式,运行结果,竟然是:
UnicodeDecodeError:&'utf8'&codec&can't&decode&byte&0xb9&in&position&0:&unexpected&code&byte
这里为什么会有utf8解码错误呢?想想上个示例也明白了,转换第一步,因为文件编码是GBK,得到的是'哈哈'编码是GBK的编码'\xb9\xfe\xb9\xfe',当进行第二步,转换成 unicode的时候,会用UTF8对'\xb9\xfe\xb9\xfe'进行解码,而大家查utf-8的编码表会发现,utf8编码表(关于UTF- 8解释可参见字符编码笔记:ASCII、UTF-8、UNICODE)中根本不存在,所以会报上述错误。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具跟老齐学Python之坑爹的字符编码
投稿:hebedich
字体:[ ] 类型:转载 时间:
本文主要介绍了在Python2.x中的编码问题,非常的坑爹,不过如果用python3,坑爹的编码问题就不烦恼了。
字符编码,在编程中,是一个让学习者比较郁闷的东西,比如一个str,如果都是英文,好说多了。但恰恰不是如此,中文是我们不得不用的。所以,哪怕是初学者,都要了解并能够解决字符编码问题。
&&& name = '老齐'
'\xe8\x80\x81\xe9\xbd\x90'
在你的编程中,你遇到过上面的情形吗?认识最下面一行打印出来的东西吗?看人家英文,就好多了
&&& name = "qiwsir"
难道这是中文的错吗?看来投胎真的是一个技术活。是的,投胎是技术活,但上面的问题不是中文的错。
什么是编码?这是一个比较玄乎的问题。也不好下一个普通定义。我看到有的教材中有定义,不敢说他的定义不对,至少可以说不容易理解。
古代打仗,击鼓进攻、鸣金收兵,这就是编码。吧要传达给士兵的命令对应为一定的其它形式,比如命令“进攻”,经过如此的信息传递:
长官下达进攻命令,传令员将这个命令编码为鼓声(如果复杂点,是不是有几声鼓响,如何进攻呢?)。
鼓声在空气中传播,比传令员的嗓子吼出来的声音传播的更远,士兵听到后也不会引起歧义,一般不会有士兵把鼓声当做打呼噜的声音。这就是“进攻”命令被编码成鼓声之后的优势所在。
士兵听到鼓声,就是接收到信息之后,如果接受过训练或者有人告诉过他们,他们就知道这是让我进攻。这个过程就是解码。所以,编码方案要有两套。一套在信息发出者那里,另外一套在信息接受者这里。经过解码之后,士兵明白了,才行动。
以上过程比较简单。其实,真实的编码和解码过程,要复杂了。不过,原理都差不多的。
举一个似乎遥远,其实不久前人们都在使用的东西做例子:电报
电报是通信业务的一种,在19世纪初发明,是最早使用电进行通信的方法。电报大为加快了消息的流通,是工业社会的其中一项重要发明。早期的电报只能在陆地上通讯,后来使用了海底电缆,开展了越洋服务。到了20世纪初,开始使用无线电拨发电报,电报业务基本上已能抵达地球上大部份地区。电报主要是用作传递文字讯息,使用电报技术用作传送图片称为传真。
中国首条出现电报线路是1871年,由英国、俄国及丹麦敷设,从香港经上海至日本长崎的海底电缆。由于清政府的反对,电缆被禁止在上海登陆。后来丹麦公司不理清政府的禁令,将线路引至上海公共租界,并在6月3日起开始收发电报。至于首条自主敷设的线路,是由福建巡抚丁日昌在台湾所建,1877年10月完工,连接台南及高雄。1879年,北洋大臣李鸿章在天津、大沽及北塘之间架设电报线路,用作军事通讯。1880年,李鸿章奏准开办电报总局,由盛宣怀任总办。并在1881年12月开通天津至上海的电报服务。李鸿章説:“五年来,我国创设沿江沿海各省电线,总计一万多里,国家所费无多,巨款来自民间。当时正值法人挑衅,将帅报告军情,朝廷传达指示,均相机而动,无丝毫阻碍。中国自古用兵,从未如此神速。出使大臣往来问答,朝发夕至,相隔万里好似同居庭院。举设电报一举三得,既防止外敌侵略,又加强国防,亦有利于商务。”天津官电局于庚子遭乱全毁。1887年,台湾巡抚刘铭传敷设了福州至台湾的海底电缆,是中国首条海底电缆。1884年,北京电报开始建设,采用"安设双线,由通州展至京城,以一端引入署中,专递官信,以一端择地安置用便商民",同年8月5日,电报线路开始建设,所有电线杆一律漆成红色。8月22日,位于北京崇文门外大街西的喜鹊胡同的外城商用电报局开业。同年8月30日,位于崇文门内泡子和以西的吕公堂开局,专门收发官方电报。
为了传达汉字,电报部门准备由4位数字或3位罗马字构成的代码,即中文电码,采用发送前将汉字改写成电码发出,收电报后再将电码改写成汉字的方法。
列位看官注意了,这里出现了电报中用的“中文电码”,这就是一种编码,将汉字对应成阿拉伯数字,从而能够用电报发送汉字。
1873年,法国驻华人员威基杰参照《康熙字典》的部首排列方法,挑选了常用汉字6800多个,编成了第一部汉字电码本《电报新书》。
电报中的编码被称为摩尔斯电码,英文是Morse Code
摩尔斯电码(英语:Morse Code)是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母、数字和标点符号。是由美国人萨缪尔·摩尔斯在1836年发明。
摩尔斯电码是一种早期的数字化通信形式,但是它不同于现代只使用0和1两种状态的二进制代码,它的代码包括五种:点(.)、划(-)、每个字符间短的停顿(在点和划之间的停顿)、每个词之间中等的停顿、以及句子之间长的停顿
看来电报员是一个技术活,不同长短的停顿都代表了不同意思。哦,对了,有一个老片子《永不消逝的电波》,看完之后保证你才知道,里面根本就没有讲电报是怎么编码的。
摩尔斯电码在海事通讯中被作为国际标准一直使用到1999年。1997年,当法国海军停止使用摩尔斯电码时,发送的最后一条消息是:“所有人注意,这是我们在永远沉寂之前最后的一声呐喊!”
我瞪着眼看了老长时间,这两行不是一样的吗?
不管这个了,总之,这就是编码。
计算机中的字符编码
先抄一段维基百科对字符编码的解释:
代码如下:字符编码(英语:Character encoding)、字集码是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数串行、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。常见的例子包括将拉丁字母表编码成摩斯电码和ASCII。其中,ASCII将字母、数字和其它符号编号,并用7比特的二进制来表示这个整数。通常会额外使用一个扩充的比特,以便于以1个字节的方式存储。
在计算机技术发展的早期,如ASCII(1963年)和EBCDIC(1964年)这样的字符集逐渐成为标准。但这些字符集的局限很快就变得明显,于是人们开发了许多方法来扩展它们。对于支持包括东亚CJK字符家族在内的写作系统的要求能支持更大量的字符,并且需要一种系统而不是临时的方法实现这些字符的编码。
在这个世界上,有好多不同的字符编码。但是,它们不是自己随便搞搞的。而是要有一定的基础,往往是以名叫ASCII的编码为基础,这里边也应该包括北朝鲜吧(不知道他们用什么字符编码,瞎想的,别当真,不代表本教材立场,只代表瞎想)。
ASCII(pronunciation: 英语发音:/ˈ&ski/ ASS-kee1,American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,而其扩展版本EASCII则可以部分支持其他西欧语言,并等同于国际标准ISO/IEC 646。由于万维网使得ASCII广为通用,直到2007年12月,逐渐被Unicode取代。
上面的引文中已经说了,现在我们用的编码标准,已经不是ASCII了,我上大学那时候老师讲的还是ASCII呢(最坑爹的是贵国的大学教育,前几天面试一个大学毕业生,计算机专业的,他告诉我他的老师给他们讲的就是ASCII为编码标准呢,我说你别埋汰老师了,你去看看教材,今天这哥们真给我发短信了,告诉我教材上就是这么说的。),时代变迁,现在已经变成了Unicode了,那么什么是Unicode编码呢?还是抄一段来自维基百科的说明(需要说明一下,本讲不是我qiwsir在讲,是维基百科在讲,我只是一个配角,哈哈)
Unicode(中文:万国码、国际码、统一码、单一码)是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。
Unicode伴随着通用字符集的标准而发展,同时也以书本的形式对外发表。Unicode至今仍在不断增修,每个新版本都加入更多新的字符。目前最新的版本为7.0.0,已收入超过十万个字符(第十万个字符在2005年获采纳)。Unicode涵盖的数据除了视觉上的字形、编码方法、标准的字符编码外,还包含了字符特性,如大小写字母。
听这名字:万国码,那就一定包含了中文喽。的确是。但是,光有一个Unicode还不行,因为....(此处省略若干字,看官可以到上面给出的维基百科连接中看),还要有其它的一些编码实现方式,Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF),于是乎有了一个我们在很多时候都会看到的utf-8。
什么是utf-8,还是看维基百科上怎么说的吧
代码如下:UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或发送文字的应用中,优先采用的编码。
不再多引用了,如果要看更多,请到原文。
看官现在是不是就理解了,前面写程序的时候,曾经出现过:coding:utf-8的字样。就是在告诉python我们要用什么字符编码呢。
encode和decode
历史部分说完了,接下怎么讲?比较麻烦了。因为不管怎么讲,都不是三言两语说清楚的。姑且从encode()和decode()两个内置函数起吧。
codecs.encode(obj[, encoding[, errors]]):Encodes obj using the codec registered for encoding.
codecs.decode(obj[, encoding[, errors]]):Decodes obj using the codec registered for encoding.
python2默认的编码是ascii,通过encode可以将对象的编码转换为指定编码格式,而decode是这个过程的逆过程。
做一个实验,才能理解:
代码如下:&&& a = "中"
&&& type(a)
&type 'str'&
'\xe4\xb8\xad'
&&& len(a)
&&& b = a.decode()
&&& type(b)
&type 'unicode'&
&&& len(b)
这个实验不做之前,或许看官还不是很迷茫(因为不知道,知道的越多越迷茫),实验做完了,自己也迷茫了。别急躁,对编码问题的理解,要慢慢来,如果一时理解不了,也肯定理解不了,就先注意按照要求做,做着做着就豁然开朗了。
上面试验中,变量a引用了一个字符串,所谓字符串(str),严格地将是字节串,它是经过编码后的字节组成的序列。也就是你在上面的实验中,看到的是“中”这个字在计算机中编码之后的字节表示。(关于字节,看官可以google一下)。用len(a)来度量它的长度,它是由三个字节组成的。
然后通过decode函数,将字节串转变为字符串,并且这个字符串是按照unicode编码的。在unicode编码中,一个汉字对应一个字符,这时候度量它的长度就是1.
反过来,一个unicode编码的字符串,也可以转换为字节串。
代码如下:&&& c = b.encode('utf-8')
'\xe4\xb8\xad'
&&& type(c)
&type 'str'&
&&& c == a
关于编码问题,先到这里,点到为止吧。因为再扯,还会扯出问题来。看官肯定感到不满意,因为还没有知其所以然。没关系,请尽情google,即可解决。
python中如何避免中文是乱码
这个问题是一个具有很强操作性的问题。我这里有一个经验总结,分享一下,供参考:
首先,提倡使用utf-8编码方案,因为它跨平台不错。
经验一:在开头声明:
# -*- coding: utf-8 -*-
有朋友问我-*-有什么作用,那个就是为了好看,爱美之心人皆有,更何况程序员?当然,也可以写成:
# coding:utf-8
经验二:遇到字符(节)串,立刻转化为unicode,不要用str(),直接使用unicode()
unicode_str = unicode('中文', encoding='utf-8')
print unicode_str.encode('utf-8')
经验三:如果对文件操作,打开文件的时候,最好用codecs.open,替代open(这个后面会讲到,先放在这里)
import codecs
codecs.open('filename', encoding='utf8')
我还收集了网上的一片文章,也挺好的,推荐给看官:Python2.x的中文显示方法
最后告诉给我,如果用python3,坑爹的编码问题就不烦恼了。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具今天看啥 热点:
[Python] 中文编码问题:raw_input输入、文件读取、变量比较等str、unicode、utf-8转换问题,& & & & 最近研究搜索引擎、知识图谱和Python爬虫比较多,中文乱码问题再次浮现于眼前。虽然市面上讲述中文编码问题的文章数不胜数,同时以前我也讲述过PHP处理数据库服务器中文乱码问题,但是此处还是准备简单做下笔记。方便以后查阅和大家学习。& & & &&中文编码问题的处理核心都是&&保证所有的编码方式一致即可,包括编译器、数据库、浏览器编码方式等,而Python通常的处理流程是将unicode作为中间转换码进行过渡。先将待处理字符串用unicode函数以正确的编码转换为Unicode码,在程序中统一用Unicode字符串进行操作;最后输出时,使用encode方法,将Unicode再转换为所需的编码即可,同时保证编辑器服务器编码方式一致。& & & &&PS:当然Python3除外!这篇文章比较啰嗦,毕竟是在线笔记和体会嘛,望理解~& & & &&在详细讲解概念之前,先讲述我最近遇到的字符编码的两个问题及解决。下图是最常见到几个问题编码问题:
&&& help(unicode)
Help on class unicode in module __builtin__:
class unicode(basestring)
unicode(object='') -& unicode object
unicode(string[, encoding[, errors]]) -& unicode object
Create a new Unicode object from the given encoded string.
encoding defaults to the current default string encoding.
errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.
& & & & 举个简单的例子:需要判断搜索词key是否在title标题中。
1 # coding=utf-8
2 import sys
4 def getTitle(key,url):
#title = driver.find_element_by_xpath()
title = u'著名女主播Miss与杰伦直播LOL'
print key,type(key)
print title,type(title)
if key in title:
print 'YES'
print 'NO'
14 key = raw_input("Please input a key: ")
15 print key,type(key)
16 url = '/'
17 getTitle(key,url)
& & & & 输出如下图所示:
s = '主播'
s.decode('utf-8').encode('gb18030')
& & & & 最后解决方法从stackoverflow得到,一方面说明自己确实研究得不是很深,另一方面那个论坛确实更强大。参考:& & & &&python raw-input odd behavior with accents containing strings& & & &&它是将终端的输入编码通过decode转换成unicode编码& & & &&key = raw_input("Please input a key: ").decode(sys.stdin.encoding)
# coding=utf-8
import sys
import urllib
import time
from selenium import webdriver
from mon.keys import Keys
import selenium.webdriver.support.ui as ui
from mon.action_chains import ActionChains
#driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")
driver = webdriver.Firefox()
wait = ui.WebDriverWait(driver,10)
def getTitle(line,info):
print 'Fun: ' + line,type(line)
driver.get("/")
elem_inp = driver.find_element_by_xpath("//form[@id='searchForm']/input")
elem_inp.send_keys(line)
elem_inp.send_keys(Keys.RETURN)
elem_value = driver.find_element_by_xpath("//div[@class='lemma-summary']/div[1]").text
print 'Summary ',type(elem_value)
print elem_value,'\n'
info.write(line.encode('utf-8')+'\n'+elem_value.encode('utf-8')+'\n')
time.sleep(5)
def main():
source = open("E:\\Baidu.txt",'r')
info = open("E:\\BaiduSpider.txt",'w')
for line in source:
line = line.rstrip('\n')
print 'Main: ' + line,type(line)
line = unicode(line,"utf-8")
getTitle(line,info)
info.close()
& & & & 其中TXT通常默认为ANSI编码,代码步骤:& & & & 1.我先把Baidu.txt修改为utf-8编码,同时读入通过unicode(line,'utf-8')将str转换为unicode编码;& & & & 2.Selenium先通过打开百度百科,在输入关键词"北京故宫"进行搜索,通过find_element_by_xpath爬取"故宫"的summary第一段内容,而且编码方式为& & & & 3.最后文件写操作,通过line.encode('utf-8')将unicode转换成utf-8,否则会报错UnicodeDecodeError: 'ascii'。& & & &&总之过程满足:编码=》Unicode=》处理=》utf-8或gbk
import codecs
#用codecs提供的open方法来指定打开的文件的语言编码,它会在读取的时候自动转换为内部unicode
info = codecs.open(baiduFile,'w','utf-8')
#该方法不是io故换行是'\r\n'
info.writelines(key.text+":"+elem_dic[key].text+'\r\n')
三. Unicode详解
& & & &PS: 该部分主要参考书籍《Python核心编程(第二版)》作者Wesley J.Chun& & & &什么是Unicode&& & & &Unicode字符串声明通过字母"u",它用来将标准字符串或者是包含Unicode字符的字符串转换成完全的Unicode字符串对象。Python1.6起引进Unicode字符串支持,是用来在多种双字节字符的格式、编码进行转换的。& & & & Unicode是计算机支持这个星球上多种语言的秘密武器。在Unicode之前,用的都是ASCII码,每个英文字符都是以7位二进制数的方式存储在计算机内,其范围是32~126。当用户在文件中键入A时,计算机会把A的ASCII码值65写入磁盘,然后当计算机读取该文件时,它会首先把65转换成字符A再显示到屏幕上。& & & & 但是它的缺点也很明显:对于成千上万的字符来说,ASCII实在太少。而Unicode通过使用一个或多个字节来表示一个字符的方法,可以表示超过90,000个字符。
&&& s1 = "中文"
'\xd6\xd0\xce\xc4'
&&& print s1,type(s1)
中文 &type 'str'&
&&& s2 = u"中文"
u'\xd6\xd0\xce\xc4'
&&& print s2,type(s2)
&OÐ&I&A &type 'unicode'&
& & & &前面添加'u'声明为Unicode字符串,但它实际的编码并没有改变。& & & &编码转码& & & &Unicode支持多种编码格式,这为程序员带来了额外的负担,每当你向一个文件写入字符串的时候,你必须定义一个编码(encoding参数)用于把对应的Unicode内容转换成你定义的格式,通过encode()函数实现;相应地,当我们从这个文件读取数据时,必须"解码"该文件,使之成为相应的Unicode字符串对象。& & & & str1.decode('gb2312') 解码表示将gb2312编码字符串转换成unicode编码& & & & str2.encode('gb2312') 编码表示将unicode编码的字符串转换成gb2312编码
&&& s = '中文'
'\xd6\xd0\xce\xc4'
&&& print s,type(s)
中文 &type 'str'&
&&& s.decode('gb2312')
u'\u4e2d\u6587'
&&& print s.decode('gb2312'),type(s.decode('gb2312'))
中文 &type 'unicode'&
&&& len(s)
&&& len(s.decode('gb2312'))
&&& t = u'中文'
u'\xd6\xd0\xce\xc4'
&&& len(t)
&&& print t,type(t)
&OÐ&I&A &type 'unicode'&
& & & & 前缀'u'表示字符串是一个Unicode串,仅仅是一个声明。& & & &&Unicode实际应用& & & & 1.程序中出现字符串时一定要加个前缀u& & & &&2.不要用str()函数,而是用unicode()代替& & & & 3.不要用过时的string模块&&如果给它的是非ASCII字符,它会把一切搞砸& & & &&4.不到必要时不要再程序里面编解码Unicode字符。只在你要写入文件或数据库或网络时,才调用encode()函数;相应地,只在需要把数据读回来时才调用decode()函数& & & & 5.由于pickle模块只支持ASCII字符串,尽量避免基于文本的pickle操作& & & &&6.假设构建一个用数据库来读写Unicode数据的Web应用,必须保持以下对Unicode的支持& & & & & && 数据库服务器(MySQL、PostgreSQL、SQL Server等)& & & & & && 数据库适配器(MySQLLdb等)& & & & & && Web开发框架(mod_python、cgi、Zope、Django等)& & & & 数据库方面确保每张表都用UTF-8编码,适配器如果不支持Unicode如MySQLdb,则必须在connect()方法里面用一个特殊的关键字use_unicode来确保得到的查询结果是Unicode字符串。mod_python开启对Unicode的支持即可,只要在request对象里面把text-encoding设为&utf-8&就OK了。同时浏览器也注意下。& & & &&总结:使用应用程序完全支持Unicode,兼容其他的语言本身就是一个工程。它需要详细的考虑、计划。所有涉及的软件、系统都需要检查,包括Python的标准库和其他要用到的第三方扩展模块。你甚至需要组件一个经验丰富的团队来专门负责国家化(I18N)问题。
四. 常用处理方法总结
& & & & 源自:http://xianglong.me/article/learn-python-1-chinese-encoding/& & & & 结合我遇到的两个问题,归纳了以下几点。常见中文编码问题解决方法包括:& & & &&1.遵循PEP0263原则,声明编码格式& & & &&在PEP 0263--Defining Python Source Code Encodings中提出了对Python编码问题的最基本的解决方法:在Python源码文件中声明编码格式,最常见的声明方式:
#!/usr/bin/python
# -*- coding: &encoding name& -*-
& & & & 根据这个声明,Python会尝试将文件中的字符编码转为encoding编码,它可以是任意一种Python支持的格式,一般都会使用utf-8\gbk的编码格式。并且它尽可能的将指定地编码直接写成Unicode文本。&& & & & 注意,coding:encoding只是告诉Python文件使用了encoding格式的编码,但是编辑器可能会以自己的方式存储.py文件,因此最后文件保存的时候还需要编码中选指定的ecoding才行。&& & & &&2.字符串变量赋值时添加前缀u,使用 u'中文' 替代 '中文'
str1 = '中文'
str2 = u'中文'
& & & & Python中有以上两种声明字符串变量的方式,它们的主要区别是编码格式的不同,其中tr1的编码格式和Python文件声明的编码格式一致,而str2的编码格式则是Unicode。& & & & 如果你要声明的字符串变量中存在非ASCII的字符,那么最好使用str2的声明格式,这样你就可以不需要执行decode,直接对字符串进行操作,可以避免一些出现异常的情况。& & & &&3.重置默认编码& & & &&Python中出现这么多编码问题的根本原因是Python 2.x的默认编码格式是ASCII,所以你也可以通过以下的方式修改默认的编码格式:sys.getdefaultencoding()默认是'ascii'编码。&
#设置编码utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
#显示当前默认编码方式
print sys.getdefaultencoding()
& & & &这种方法是可以解决部分编码问题,但是同时也会引入很多其他问题,得不偿失,不建议使用这种方式。& & & &其原理: 首先, 这个就是Python语言本身的问题。因为在Python 2.x的语法中, 默认的str并不是真正意义上我们理解的字符串, 而是一个byte数组, 或者可以理解成一个纯ascii码字符组成的字符串, 与Python 3中的bytes类型的变量对应; 而真正意义上通用的字符串则是unicode类型的变量, 它则与Python 3中的str变量对应。本来应该用作byte数组的类型, 却被用来做字符串用, 这种看似奇葩的设定是Python 2一直被人诟病的东西, 不过也没有办法, 为了与之前的程序保持兼容.。& & & &在Python 2中作为两种字符串类型, str与unicode之间就需要各种转换的方式。首先是一种显式转换的方式, 就是encode和decode两种方法。在这里这两货的意思很容易被搞反, 科学的调用方式是:&& & & &str --- decode方法 ---& unicode&& & & &unicode --- encode方法 ---& str&& & & &4.终极原则:decode early, unicode everywhere, encode late& & & &Decode early:尽早decode, 将文件中的内容转化成unicode再进行下一步处理&& & & &Unicode everywhere:程序内部处理都用unicode,比如字符串拼接、替换、比较等操作 &&& & & &Encode late:最后encode回所需的encoding, 例如把最终结果写进结果文件&& & & &按照这个原则处理Python的字符串,基本上可以解决所有的编码问题(只要你的代码和Python环境没有问题)。前面讲述的两个问题解决实质也是这样,只是有些取巧即可。& & & &5.使用decode().encode()方法& & & &网页采集时,代码指定#coding:utf-8,如果网页的编码为gbk需要这样处理:& & & &html = html.decode('gbk').encode('utf-8')& & & &6.输入变量raw_input中文编码& & & &将终端的输入编码str通过decode转换成unicode编码,再使用unicode处理:& & & &key = raw_input("Please input a key: ").decode(sys.stdin.encoding)& & & &7.文件读写操作& & & &由于默认的txt文件为ANSI编码,读取时通过unicode转码,经过&编码=》Unicode=》处理=》utf-8或gbk&&顺序即可。同时文件输出时encode('utf-8')转换txt为UTF-8格式。终极代码:& & & &info = codecs.open(baiduFile,'w','utf-8')& & & &&8.升级Python 2.x到3.x& & & & 最后一个方法:升级Python 2.x,使用Python 3.x版本。这样说主要是为了吐槽Python 2.x的编码设计问题。当然,升级到Python 3.x肯定可以解决大部分因为编码产生的异常问题。毕竟Python 3.x版本对字符串这部分还是做了相当大的改进的。& & & & 在Python 3.0之后的版本中,所有的字符串都是使用Unicode编码的字符串序列,同时还有以下几个改进:& & & &&& 默认编码格式改为unicode& & & & &&所有的Python内置模块都支持unicode& & & & & 不再支持u'中文'的语法格式& & & & 所以,对于Python 3.x来说,编码问题已经不再是个大的问题,基本上很少遇到上述的几个异常。
& & & & 最后希望文章对你有所帮助,尤其是你刚好遇到这个问题的,由于是结合最近做的东西,所以文章比较杂乱,但如果你刚好需要,确实能解决你的问题的。& & & &&纪伯伦曾说过:&你无法同时拥有青春和关于青春的知识;因为青春忙于生计,没有余暇去求知;而知识忙于寻求自我,无法享受生活。&& & & & 同样现在找工作的我,无法在拥有扎实基础知识的同时又兼顾深度的项目理解,但我更倾向于分享知识,因为它就是寻求自我,就是享受生活,就是编程之乐~
& & & & (By:Eastmount
晚上11点&http://blog.csdn.net/eastmount/)
暂无相关文章
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&
Python教程最近更新

我要回帖

更多关于 python 编码问题 的文章

 

随机推荐