python2.7 编码问题

Python报错:unicodedecodeerror ascii codec can t decode byte 0xe5 in position 0 ordinal not in range 128

那些年我们用Python读写中文遇到的乱码问题及IDLE中文编码问题

在报错的页面添加代码: import sys
reload(sys)
sys.setdefaultencoding(‘utf8’)

执行 Python ez_setup.py,报错:

UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0xb0 in position 35: invalid
start byte

解决办法:

在报错的页面添加代码: import sys
reload(sys)
sys.setdefaultencoding(‘gb18030’)

然后再执行 Python ez_setup.py,成功了

字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。

decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode(‘gb2312’),表示将gb2312编码的字符串str1转换成unicode编码。

encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode(‘gb2312’),表示将unicode编码的字符串str2转换成gb2312编码。

因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码

(与代码本身的编码是一致的!)

测试:
我的eclipse里面代码为utf-8编码的。然后我这样写代码
s=”你好”
s=s.decode(‘gb2312’).encode(‘utf-8’)
print s
报错:
UnicodeDecodeError: ‘gb2312’ codec can’t decode bytes in position 2-3: illegal multibyte sequence
原因:因为我的文件为UTF-8编码的。所以你想用gb2312将其转成unicode是不可能的。
所以正确的写法应当是:
s=”你好”
print s
s=s.decode(‘utf-8’).encode(‘utf-8’) 要用UTF-8来做编码
print s
哈哈发现打印出来的是乱码那只能说明一件事情就是我的eclipse控制台是GB2312的编码!

请看:
如何获得系统的默认编码?

!/usr/bin/env python

coding=utf-8

import sys
print sys.getdefaultencoding()

该段程序在英文WindowsXP上输出为:ascii 。我发现我的linux上面也是ascii编码。所以我想打印出来看到的乱码是正常的。因为我其实是utf-8编码的。

在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。(是的。我的eclipse控制台就是gb2312的编码所以我文件保存为utf-8的时候然后再通过打印是乱码了!)

1、读文件命令肯定是:
myfile = codecs.open(“c.html”,”r”,”utf-8”) 因为我用gb2312来读的话报错

心得:检查一个字符串是什么编码只需要看一下decode 如果用gb2312来decode没报错的话就表示是gb2312
如果用utf-8来decode没有报错的话就表示是utf-8

现在遇到一个问题就是
请看:
myfile = codecs.open(“c.html”,”r”,”utf-8”)
str = myfile.read()
content = str.replace(“\n”,” “)
content = content.encode(‘utf-8’)
print content
没有报错
再看:
myfile = codecs.open(“c.html”,”r”,”utf-8”)
str = myfile.read() #显示中文
content = str.replace(“\n”,” “)
content = content.encode(‘gb2312’) 用gb2312
print content
报错:UnicodeEncodeError: ‘gb2312’ codec can’t encode character u’\u2014’ in position 12628

再看:
myfile = codecs.open(“d.html”,”r”,”utf-8”)
str = myfile.read() #显示中文
content = str.replace(“\n”,” “)
content = content.encode(‘gb2312’) 用gb2312
print content
没问题
myfile = codecs.open(“d.html”,”r”,”utf-8”)
str = myfile.read() #显示中文
content = str.replace(“\n”,” “)
content = content.encode(‘utf-8’)
print content
也没问题

结论:我想是c.html页面里面 存在某些 特殊字符 只支持utf-8编码。而不支持gb2312的编码!
而d.html没有这种特殊字符。这也就解释了为什么
有的文件并没有发生我们想像中的问题!

所以我感觉打开文件肯定是用utf-8来读取得到一个unicode编码值!
然后对其做utf-8的编码处理。因为如果你做gb2312处理的话就会报错了!

接着:
我看了一下我的正则表达式发现如果用gb2312做解码处理的话一样会报错。所以断定肯定是utf-8编码了!
regex3 = regex3.decode(‘utf-8’)
print type(regex3) #返回为unicode码了!
print regex3 #居然打印为正常的中文显示了 奇怪

尝试解决办法:
1、全部用unicode处理
即正则我用regex3 = regex3.decode(‘utf-8’) 将其处理成 unicode编码了。然后内容也
print type(content) 也是unicode编码。结果还是不行!

难道是我的linux终端的编码引起的吗?我看了一下
locale 发现是GBK的终端的。即只有GBK编码才能显示出来为中文的!
于是我将
regex3 = regex3.decode(‘utf-8’).encode(‘gb2312’) 编码成gb2312结果可以显示中文!

OK。我又将我的内容也一起弄成GB2312
content = content.encode(‘gb2312’,’ignore’)
print content 也可以成功打印出来中文。

我想这个时候应该没有什么问题了吧。结果一用正则又死掉了。昏死!!!!!!!

换另外一个好的文件测试下看看:换了之后发现没死而且成功了!

所以我觉得:肯定是这个文件里面的某些内容与正则匹配出现了冲突!导致的!

继续跟踪:
出现如下的情况
myfile = codecs.open(“01.htm”,”r”,”utf-8”,”ignore”)
str = myfile.read()
content = str.replace(“\n”,” “)
print type(content) #发现是unicode码
regex3 = ‘class=wpcpsCSS>([^<]+)(?:.?wpcppb_CSS> ([0-9]+) )?.?(?:.?(已被关闭))?.?([0-9]+)个回答.?([0-9]+)次浏览.?(?:

.?user\?userid=([0-9]+).?>(.?)

.?)?(?:user\?userid=([0-9]+)”)? class=”wpfitCSS[^”]+”>([^<]+). ?class=wpcptsCSS>([^<]+).?([0-9.]{9,}*). ?class=wpcpdCSS>(.?)


content = content.encode(‘utf-8’)
p=re.compile(regex3)
results = p.findall(content)

没有什么问题可以成功出来结果。但是我
将content = content.encode(‘gb2312’) 的话就发现 死掉了!
说明我的内容content与我的正则的编码其实是不一样的!
我现在将我的正则也调成gb2312来测试。结果发现可以出来。而且我的结果
results = p.findall(content)
for ele in results:
print ele[0],ele[1],ele[2],ele[3],ele[4],ele[5],ele[6],ele[7],ele[8],ele[9],ele[10]
在eclipse(默认为gb2312)下面也是没有问题的了!~

所以我想:如果content是GBK那正则的内容也应当是GBK 即两者的编码一定要保持一致!否则就会出现死掉程序的情况!

现在我这样来处理
全部使用unicode编码处理

myfile = codecs.open(“right.html”,”r”)
str = myfile.read()
content = str.replace(“\n”,” “)
content = content.decode(‘utf-8’,’ignore’) #使用utf-8解码出来
都使用unicode编码吧
现在正则也用
regex3 = regex3.decode(‘utf-8’,’ignore’) 使用utf-8搞成unicode编码

OK现在再来测试!

结论:
解决正则出现中文的BUG结论:
1、打开文件
myfile = codecs.open(“right.html”,”r”)
不需要设置其编码的!

设置编码格式
str = myfile.read()
content = str.replace(“\n”,” “)
content = content.decode(‘utf-8’,’ignore’) #使用utf-8解码成unicode格式

正则:
regex3 = regex3.decode(‘utf-8’,’ignore’) #正则也统一使用utf-8解码成unicode格式

然后就可以
p=re.compile(regex3)
results = p.findall(content)
调用正则了!

字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。
idle默认是ASCII编码,中文在显示时会做一个ASCII到系统默认编码的转换,这时就会出错:SyntaxError: Non-ASCII character。需要在代码文件的第一行或第二行添加编码指示:
# coding=utf-8 ##以utf-8编码储存中文字符
print ‘中文’像上面那样直接输入的字符串是按照代码文件的编码来处理的,如果用unicode编码,有以下三种方式:
s1 = u’中文’ #u表示用unicode编码方式储存信息
s2 = unicode(‘中文’,’gbk’)
unicode是一个内置函数,第二个参数指示源字符串的编码格式。
decode是任何字符串具有的方法,将字符串转换成unicode格式,参数指示源字符串的编码格式。
encode也是任何字符串具有的方法,将字符串转换成参数指定的格式。

字符串的编码
用 u’汉字’ 构造出来的是unicode类型,不用的话构造出来是str类型
str的编码是与系统环境相关的,一般就是sys.getfilesystemencoding()得到的值
所以从unicode转str,要用encode方法
从str转unicode,所以要用decode
例如:
# coding=utf-8 #默认编码格式为utf-8
s = u’中文’ #unicode编码的文字
print s.encode(‘utf-8’) #转换成utf-8格式输出
print s #效果与上面相同,似乎默认直接转换为指定编码

总而言之:
u=u’unicode编码文字’
g=u.encode(‘gbk’) #转换为gbk格式
print g #此时为乱码,因为当前环境为utf-8,gbk编码文字为乱码
str=g.decode(‘gbk’).encode(‘utf-8’) #以gbk编码格式读取g(因为他就是gbk编码的)并转换为utf-8格式输出
print str #正常显示中文

安全的方法:
s.decode(‘gbk’,’ignore’).encode(‘utf-8′) #以gbk编码读取(当然是读取gbk编码格式的文字了)并忽略错误的编码,转换成utf-8编码输出

因为decode的函数原型是decode([encoding], [errors=’strict’]),可以用第二个参数控制错误处理的策略,默认的参数就是strict,代表遇到非法字符时抛出异常;
如果设置为ignore,则会忽略非法字符;
如果设置为replace,则会用?取代非法字符;
如果设置为xmlcharrefreplace,则使用XML的字符引用。
———————————————-更新——————————–
在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。
如在UliPad中运行如下代码:
s=u”中文”
print s
会提示:UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-1: ordinal not in range(128)。这是因为UliPad在英文WindowsXP上的控制台信息输出窗口是按照ascii编码输出的(英文系统的默认编码是ascii),而上面代码中的字符串是Unicode编码的,所以输出时产生了错误。
将最后一句改为:print s.encode(‘gb2312’)
则能正确输出“中文”两个字。
若最后一句改为:print s.encode(‘utf8’)
则输出:\xe4\xb8\xad\xe6\x96\x87,这是控制台信息输出窗口按照ascii编码输出utf8编码的字符串的结果。
unicode(str,’gb2312’)与str.decode(‘gb2312’)是一样的,都是将gb2312编码的str转为unicode编码
使用str.class可以查看str的编码形式

Windows 下IDLE中文编码:(弄死人不偿命啊!)

s = “撒旦法”
s
‘\xc8\xf6\xb5\xa9\xb7\xa8’
text = U”亲爱的,你好吗,我好想念你!”
text
u’\xc7\xd7\xb0\xae\xb5\xc4\xa3\xac\xc4\xe3\xba\xc3\xc2\xf0\xa3\xac\xce\xd2\xba\xc3\xcf\xeb\xc4\xee\xc4\xe3\xa3\xa1’
可以看出,对于不使用“u”作标识的字符串,IDLE把其中的中文字符进行GBK编码。但是对于使用“u”的unicode字符串,IDLE居然一样是用了GBK编码,不同的是,这时候每一个字符都是unicode(对象)字符!!
这样就有个问题,text无法在IDLE中正常显示。而且我也没有办法把text转换成正常的编码!比如:
print text.encode(‘gb2312’)

Traceback (most recent call last):
File “

-- coding:utf-8 --

text = “亲爱的,你好吗,我好想念你!”
m = re.findall(ur”你好”, text.decode(“utf-8”))
if m:
print m[0].encode(‘gb2312’)
else:
print “not match!”

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值