【python编码】 UnicodeDecodeError 分析和解决

现象

环境是linux,python2.7,执行以下代码:

import json

a = '{"task_id": ["8061964"], "ch_reason": "\u589e\u52a0\u534f\u8bae\u7ba1\u7406\u6a21\u5757\uff0c\u7528\u6765\u7ba1\u7406\u5b58\u6b3e\u4ea7\u54c1\u7684\u6cd5\u5f8b\u534f\u8bae", "chg_type": ["0"]}'
aa = json.loads(a)
b = '变更原因'
c = b + aa['ch_reason']
print c

 

出现如下异常:


原因

unicode指的是万国码,是一种“字码表”。而utf-8是这种字码表储存的编码方法。unicode不一定要由utf-8这种方式编成bytecode储存,也可以使用utf-16,utf-7等其他方式。目前大多都以utf-8的方式来变成bytecode。

其中,python里的字符串类型分为byte string 和 unicode string两种。

如果在python文件中指定编码方式为utf-8(#coding=utf-8),那么所有带中文的字符串都会被认为是utf-8编码的byte string(例如:mystr="你好"),但是在函数中所产生的字符串则被认为是unicode string。


问题就出在这边,unicode string 和 byte string 是不可以混合使用的,一旦混合使用了,就会产生如上的错误。

解决方案

方案一:修改全局默认编码

import sys
reload(sys)
sys.setdefaultencoding('utf-8')


缺点:一旦加载就修改了全局的编码,有风险。优点:简单粗暴。

 

方案二:手动将unicode对象的编码改为utf-8

将unicode对象的编码改为utf-8,即可和python 中的byte string 之间互相操作了。

def unicode_convert(input):
    if isinstance(input, dict):
        return {unicode_convert(key): unicode_convert(value) for key, value in input.iteritems()}
    elif isinstance(input, list):
        return [unicode_convert(element) for element in input]
    elif isinstance(input, unicode):
        return input.encode('utf-8')
    else:
        return input

def test():
	unicode_obj = u'我是unicode'
	str_obj = unicode_convert(unicode_obj)
	assert isinstance(str_obj, str)


如果要在json反序列化中使用,还可以使用以下方式: 

json.loads(unicode_obj, object_hook=unicode_convert)


优点:按需转换。 

缺点:可能有遗漏。

总结

方案二更加合适。

posted @ 2021-01-26 20:12  puyangsky  阅读(1364)  评论(0编辑  收藏  举报