python ascii转utf8的UTF-8问题

adapted by文件读取 python读取中文文本文件的GBK和UTF-8编码问题 - 为程序员服务
为程序员服务
python读取中文文本文件的GBK和UTF-8编码问题
如果文件是gbk的
# -*- coding: utf-8 -*-
for row in open('c:\\1.txt').readlines():
print row.find(u'脚本分享网')
如果文件是utf8的
# -*- coding: utf-8 -*-
for row in open('c:\\1.txt').readlines():
print row.decode('utf8').encode('gbk')
print row.find(u'脚本分享网')
您可能的代码
相关聚客文章
荣誉:1095
相关专栏文章Python编码问题详解
Python编码问题详解
继上一篇文章字符集和编码详解总结了常见字符编码后,这篇文章会对python中常见的编码问题进行分析和总结。由于python3.x版本和python2.x版本在字符编码方面有很大差异,所以本文都是以Python2.7.5来分析2.x版本中的字符编码问题。
1.Python编码基础
1.1 str和unicode
python中有两种数据模型来支持字符串这种数据类型,str和unicode,它们的基类都是basestring。比如s = "中文"就是str类型的字符串,而u=u"中文"就是一个unicode类型的字符串。unicode是由str类型的字符串解码后得到,unicode也可以编码成str类型。即
str --> decode -->unicode
unicode --> encode --> str
严格来说,str也许应该叫做字节串,因为对于UTF-8编码的str类型"中文",使用len()函数得到的结果是6,因为UTF-8编码的str类型“中文”实际是"\xe4\xb8\xad\xe6\x96\x87"。而对于unicode类型u“中文”(实际是u"\u4e2d\u6587"),使用len()函数得到结果是2.
1.2 头部编码声明
在python源代码文件中如果有用到非ascii字符,比如中文,那么需要在文件头部声明源代码字符编码,格式如下:
#-*- coding: utf-8 -*-
这个格式看起比较复杂,其实python只检查#、coding,编码等字符串,可以简写成#coding:utf-8,甚至还可以写成#coding:u8。
2.2.x常见编码问题
2.1 头部编码声明和文件编码问题
文件头部编码声明决定了python解析源码中的str的编码选择方式,比如头部声明的是utf-8编码,则代码中s="中文"python就会按照utf-8编码格式来解析,通过repr(s)可以看到字符编码是"\xe4\xb8\xad\xe6\x96\x87",如果头部声明的编码是gbk编码,则python会对s采用gbk编码解析,结果是"\xd6\xd0\xce\xc4"。
需要注意的是,文件本身的编码要跟文件头部声明编码一致,不然就会出现问题。文件本身的编码在下面可以在vim下用命令set fenc来查看。如果文件本身编码是gbk,而源码文件头部声明的编码是utf-8,这样如果源码中有中文就会有问题了,因为本身中文str存储是按照gbk编码来的,而python在解析str的时候又以为是utf-8编码,这样就会报SyntaxError: (unicode error) 'utf8' codec can't decode byte错误。
2.2 默认编码问题
下面看个python默认编码导致的问题:
#coding: utf-8
u = u"中文"
print repr(u) # u'\u4e2d\u6587'
s = "中文"
print repr(s) # '\xe4\xb8\xad\xe6\x96\x87'
u2 = s.decode("utf-8")
print repr(u2) # u'\u4e2d\u6587'
#s2 = u.decode("utf-8") #编码错误
#u2 = s.encode("utf-8") #解码错误
注意实例中注释掉的2行代码,对于unicode最好不要直接调用decode,str最好不要直接调用encode方法。因为如果是直接调用,则相当于u.encode(default_encoding).decode("utf-8"),default_encoding是python的unicode实现中用的默认编码,即sys.getdefaultencoding()得到的编码,如果你没有设置过,那么默认编码就是ascii,如果你的unicode本身超出了ascii编码范围就会报错。同理,如果对str直接调用encode方法,那么默认会先对str进行解码,即s.decode(default_encoding).encode("utf-8"),如果str本身是中文,而default_encoding是ascii的话,解码就会出错,从而导致上面这两行会分别报UnicodeEncodeError: 'ascii' codec can't encode characters in position...错误和UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position...错误。
上面例子中注释掉的两行代码如果执行就会报错,当然,如果本身str或者unicode都在ascii编码范围,就没有问题。比如s = "abc"; s.encode("utf-8")就不会有问题,语句执行后会返回一个跟s的id不同的str。
那如果要解决实例1中的问题,有两种方法,其一是明确指定编码,如下所示:
#coding: utf-8
u = u"中文"
print repr(u) # u'\u4e2d\u6587'
s = "中文"
print repr(s) # '\xe4\xb8\xad\xe6\x96\x87'
u2 = s.decode("utf-8")
print repr(u2) # u'\u4e2d\u6587'
s2 = u.encode("utf-8").decode("utf-8")
u2 = s.decode("utf8").encode("utf-8")
第二种方法就是更改python的默认编码为文件编码格式,如下所示(这里只所以要reload sys模块,是因为python初始化后删除了setdefaultencoding方法):
#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8") #更改默认编码为utf-8
u = u"中文"
print repr(u) # u'\u4e2d\u6587'
s = "中文"
print repr(s) # '\xe4\xb8\xad\xe6\x96\x87'
u2 = s.decode("utf-8")
print repr(u2) # u'\u4e2d\u6587'
s2 = u.decode("utf-8")
u2 = s.encode("utf-8")
2.3读写文件编码
采用python的open()方法打开文件时,read()读取的是str,编码就是文件本身的编码。而调用write()写文件时,如果参数是unicode,则需要用指定编码encode,如果write()参数是unicode而且没有指定编码,则会采用python默认编码encode后再写入。
#coding:utf-8
f = open("testfile")
s = f.read()
print type(s) #
u = s.decode("utf-8") #testfile是utf-8编码
f = open("testfile", "w")
f.write(u.encode("gbk")) #以gbk编码写入,testfile为gbk编码
此外,python的codecs模块提供了一个open()方法,可以指定编码打开文件,使用这个方法打开文件读取返回是unicode。写入时,如果write参数是unicode,则使用打开文件时的编码写入,如果是str,则先使用默认编码解码成unicode后再以打开文件的编码写入(这里需要注意如果str是中文,而默认编码sys.getdefaultencoding()是ascii的话会报解码错误)。
#coding:gbk
import codecs
f = codecs.open('testfile', encoding='utf-8')
u = f.read()
print type(u) #
f = codecs.open('testfile', 'a', encoding='utf-8')
f.write(u) #写入unicode
# 写入gbk编码的str,自动进行解码编码操作
s = '汉'
print repr(s) # '\xba\xba'
# 这里会先将GBK编码的str解码为unicode再编码为UTF-8写入
#f.write(s) #默认编码为ascii时,这会报解码错误。
3.参考资料
python字符编码详解
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。Python中GBK, UTF-8和Unicode的编码问题 - 为程序员服务
Python中GBK, UTF-8和Unicode的编码问题
编码问题,一直是使用python2时的一块心病。几乎所有的控制台输入输出、IO操作和HTTP操作都会涉及如下的编码问题:
UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xc4 in position 10: ordinal not in range(128)
这究竟是是个什么东西?!有时稀里糊涂地用一坨encode(),decode()之类的函数让程序能跑对了,可是下次遇到非ASCII编码时又悲剧了。
那么Python 2.x中的字符串究竟是个什么呢?
基本编码知识
在了解Python中字符串(String)的本质前,我们需要知道ASCII、GBK、UTF-8和Unicode的关系究竟几何。
我们知道,任何字符串都是一串二进制字节的序列,而ASCII码是最经典的编码方式,它将序列中的每个字节理解为一个字符,可表示阿拉伯数字、字母在内的128个不同字符。很明显,汉字在ascii中是无法表示的。
为了让计算机能够显示、处理汉字,勤劳朴实的中国人民制定了GBK(GB2312的扩展)编码,这是一种兼容ASCII的不定长(长度为1-2)编码,对于基本的128个字符仍旧用一个字节表示,但“翔”这样的中文就用两个字节表示:
UTF-8与GBK类似,也是一种兼容ASCII码的不定长编码形式,它的长度变化更大,因此可以表示几乎所有世界文字。具体细节可参考维基:
Unicode是一种定长的编码方式(同ASCII),不过它是每2字节认为是一个字符,如ASCII中0x61表示'a',在Unicode中用0x0061表示'a',它可映射所有文字,而且对于多种写法的字,如強/强,它都可以唯一地区分它们。
由于Unicode编码的字符串体积很大,因此一般来说Unicode编码只是文字在内存中的内在形式,具体的存储(如文件、网页等)都需要靠外在的编码(UTF-8、GBK等)诠释。
Python2.x中字符串的本质
Python中实际上有两种字符串,分别是str类型和unicode类型,这两者都是basestring的派生类。它们的区别如下:
字符串类型
常量子串表示
内存中表示
S=“呵呵”
与源码文件完全一致,一坨二进制编码
若源码文件为UTF-8编码,
S=u“呵呵”
Unicode编码
str类型的本质就是一坨二进制串,源文件(或获取的网页)的编码是怎样,它就跟着是怎样。实际上Python并不清楚某个str字符串到底是什么编码。这也就解释了为什么我们需要在python文件的开头标定该文件的编码是什么,如:
# encoding: utf-8
也解释了为什么len()一个str类型的字符串,只会返回它在内存中占用的字节数,而非文字数。
相比于str,unicode是真正的字符串。Python明确地知道它的编码,所以可以很自信地获得一个字符串的实际字数。
字符串编码转换:encode()和decode()
Python最常用的编码转换函数是encode()和decode(),他们的本质是:unicode和str的互相转换。
具体而言:
encode(encoding): 将unicode转换为str,并使用encoding编码;
decode(encoding):将str转换为unicode,其中str以encoding编码。
我们来看一个例子:
#encoding: utf-8
s = &你好& # 整个文件是UTF-8编码,所以这里的字符串也是UTF-8
u = s.decode(&utf-8&) # 将utf-8的str转换为unicode
g = u.encode('GBK') # 将unicode转换为str,编码为GBK
print type(s), &len=&, len(s)
# 输出:&type 'str'& len= 6,utf-8每个汉字占3字节
print type(u), &len=&, len(u)
# 输出:&type 'str'& len= 6,unicode统计的是字数
print type(g), &len=&, len(g)
# 输出:g = u.encode('GBK'),GBK每个汉字占2字节
# 在GBK/ANSI环境下(如Windows),输出乱码,
#因为此时屏幕输出会被强制理解为GBK;Linux下显示正常
# 在Windows下输出“你好”,
#Linux(UTF-8环境)下报错,原因同上。
在Windows7(中文)下运行结果如下:
&type 'str'& len= 6
&type 'unicode'& len= 2
&type 'str'& len= 4
Traceback (most recent call last):
File &C:/Users/Sunicy/Desktop/encode.py&, line 15, in &module&
g.decode('utf-8')
File &C:\Python27\lib\encodings\utf_8.py&, line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xc4 in position 0: invalid continuation byte
判断变量是否为字符串
我们知道Python中判断一个变量是否为某个类型使用isinstance(变量, 类型)函数,如
isinstance(1.2, float)
返回值为True
那么判断变量是不是字符串能不能用
isinstance(s, str)
答案是否定的。
现在我们知道除了str之外,unicode类型也是字符串,因此上述代码如果遇到unicode字符串,就返回False。
直观地改进是既判断str又判断unicode:
isinstance(s, str) or isinstance(s, unicode)
不过这个方法有效,但是有点傻。既然str和unicode都派生自basestring,那么实际上以basestring作为类型是最稳妥的:
isinstance(s, basestring)
下面是一组例子:
isinstance(&aaa&, str) # -& True
isinstance({}, dict) # -& True
isinstance([1,], list) # -& True
isinstance(&aaa&, list) # -& False
isinstance(&你&, str) # -& False
isinstance(&你好&, basestring) # -& True
isinstance(&aaa&, basestring) # -& True
unicode是支持所有文字的统一编码,但一般只用作文字的内部表示,文件、网页(也是文件)、屏幕输入输出等处均需使用具体的外在编码,如GBK、UTF-8等;
encode和decode都是针对unicode进行“编码”和“解码”,所以encode是unicode-&str的过程,decode是str-&unicode的过程;
unicode和str是一对孪生兄弟,来自basestring,所以用isinstance(s, basestring)来判断s是否为字符串。
付出与简单的收获
原文地址:, 感谢原作者分享。
您可能感兴趣的代码页面导航:
→ 正文内容 python编码
学习python处理python编码问题
概括从python开始就处理unicode字符,python源文件的编码与解码,我们写的python程序从产生到执行的过程如下
概括、从python1.6开始就可以处理unicode字符了。 一、几种常见的编码格式。 1.1、ascii,用1个字节表示。 1.2、UTF-8,用1个至三个字节表示,表示ascii码时只占用1个字节,ascii编码是UTF-8的子集。 1.3、UTF-16,用2个字节表示,在python中,unicode的含义就是UTF-16。 二、python源文件的编码与解码,我们写的python程序从产生到执行的过程如下: 编辑器----&源代码----&解释器----&输出结果 2.1、编辑器决定源代码的编码格式(在编辑器中设定) 2.2、也必须要解释器知道源代码的编码格式(很遗憾很难从编码的数据获知源文件的编码格式) 2.3、补充:在Windows下当用UltraEdit把源代码存成UTF-8时,会在文件中记录BOM标志(不必祥究)这样ActivePython解释器会自动识别源文件是UTF-8格式,但是如果用eclipse编辑源文件,虽然在编辑器中指定文件编码为UTF-8,但是因为没有记入BOM标志,所以必须在源文件开始处加上#coding=utf-8,用注释来提示解释器源文件的编码方式挺有意思。 2.4、举例:例如我们要向终端输出"我是中国人"。
代码如下: #coding=utf-8 告诉python解释器用的是utf-8编码,我用的是eclipse+pydev print "我是中国人" #源文件本身也要存成UTF-8编码
三、编码的转换,两种编码的转换要用UTF-16作为中转站。 举例:如果有一个文本文件jap.txt,里面有内容 "私は中国人です。",编码格式是日文编码SHIFT_JIS, 还有一个文本文件chn.txt,内容是"中华人民共和国",编码格式是中文编码GB2312。 我们如何把两个文件里的内容合并到一起并存储到utf.txt中并且不显示乱码呢,可以采用把两个文件的内容都转成UTF-8格式,因为UTF-8里包含了中文编码和日文编码。
代码如下: #coding=utf-8 try: JAP=open("e:/jap.txt","r") CHN=open("e:/chn.txt","r") UTF=open("e:/utf.txt","w") jap_text=JAP.readline() chn_text=CHN.readline() #先decode成UTF-16,再encode成UTF-8 jap_text_utf8=jap_text.decode("SHIFT_JIS").encode("UTF-8") #不转成utf-8也可以 chn_text_utf8=chn_text.decode("GB2312").encode("UTF-8")#编码方式大小写都行utf-8也一样 UTF.write(jap_text_utf8) UTF.write(chn_text_utf8) except IOError,e: print "open file error",e
四、Tk库支持ascii,UTF-16,UTF-8
代码如下: #coding=utf-8 from Tkinter import * try: JAP=open("e:/jap.txt","r") str1=JAP.readline() except IOError,e: print "open file error",e root=Tk() label1=Label(root,text=str1.decode("SHIFT_JIS")) #如果没有decode则显示乱码 label1.grid() root.mainloop()
以上是学习python处理python编码的基本过程,希望对大家有帮助。
您可能感兴趣的文章:
上一篇:下一篇:
最 近 更 新
热 点 排 行
12345678910}

我要回帖

更多关于 python unicode转utf8 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信