开源中文网

您的位置: 首页 > 编程开发 > python > 正文

如何处理python编码转换时的UnicodeDecodeError异常

来源:  作者:

python提供的unicode转换不像iconv或是mbstowcs之类的方便。 

如果转换一段 unicode("1234中文",'ascii') 到utf8会直接出现UnicodeDecodeError的错误。如果在你能预知字串符的编码的时候,比如你用unicode('1234中文', 'gbk') 就不会出现错误,不过很多时候,会出现CJK混合的情况,如果要做到将一段CJK文件转换成unicode可能就行不通了。 

好在python的codecs提供了register_error这个功能: 
register_error( name, error_handler) 

原理很简单,不过要先看unicode是如何处理异常的,unicode这个函数是将一段string按输入的编码转换成目标的编码,如果出现了不与输入编码相符的,会出现一个UnicodeDecodeError的异常,通常有三种处理方法:strict,replace,ignore,默认是 strict,就是直接raise UnicodeDecodeError. 通过register_error,我们也可以有自己的处理方法,如果遇到与输入的编码不符的时候,我们就自己识别,比如GBK的,比如BIG5,比如 JP的。 


def cjk_replace(exc): 
if not isinstance(exc, UnicodeDecodeError): 
raise TypeError("don't know how to handle %r" % exc) 

if exc.end + 1 > len(exc.object): 
raise TypeError('unknown codec ,the object too short!') 

ch1 = ord(exc.object[exc.start:exc.end]) 
newpos = exc.end + 1 
ch2 = ord(exc.object[exc.start + 1:newpos]) 
sk = exc.object[exc.start:newpos] 


if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK 
return (unicode(sk,'cp936'), newpos) 

if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5 
return (unicode(sk,'big5'), newpos) 

raise TypeError('unknown codec !') 

codecs.register_error("cjk_replace", cjk_replace) 

我们的cjk_replace现在只能处理GBK与BIG5的,因为我对编码也不是特别了解,所以就大概知道GBK与BIG5的,JP的不知道是什么.在 cjk_replace这个函数里,我们对不认识的文字进行手工识别,如果认识的编码,就用正确的方法,并返回编码后的内容与新的pos, 
比如"1234中文",在pos为4的时候,会调用我们的cjk_replace,我们会返回一个从gbk转换成utf8的’中‘字,并返回下个正确的位置‘文’的起始位置。当然了,处理‘文’的时候,还会再调用一次。T_T 

看看是如何使用的 
filedata = open('test.txt','r).read() #gbk and big5 file 
data = unicode(filedata,'ascii','cjk_replace').encode('utf8')

Tags:编码
关于开源中文网 - 联系我们 - 广告服务 - 网站地图 - 版权声明