微信号:grzlwx

介绍:光荣之路官方资讯

干货:Python的encode与decode(续)

2016-01-20 23:03 光荣之路

吴老的《selenium webdriver 实战宝典》出版了!

相关阅读:Python的encode与decode

二、常见报错codec can't encode characters的原因

python的程序经常会报错codec can't encode characterscodec can't decode characters

在python中定义一个字符串,

import sys
print sys.getdefaultencoding() # 输出 ascii
unicode_test=u'测试test'
print repr(str(unicode_test))

上面的代码会报错

 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

除了str方法外,如果操作两个都有中文的字符串,也会报错,但是只有其中一个有中文,却不会报错

unicode_test = u'测试test%s{0}'

print '%stest' % unicode_test  # 不会报错
print '%s测试' % unicode_test  #会报错

print unicode_test % 'test'  #不会报错
print unicode_test % '测试'  #会报错

print unicode_test.format('test') #不会报错
print unicode_test.format('测试') #会报错

print unicode_test.split('test')  #不会报错
print unicode_test.split('测试')  #报错

print unicode_test + 'test'  #不会报错
print unicode_test + '测试'  #会报错

为什么会这样?
这原因下面再解答,这里先列出这个报错的解决方法:
解决方法是:把系统的默认编码设置为utf-8

import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print sys.getdefaultencoding()
unicode_test=u'测试test'

demo3.py
# encoding=utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
unicode_test=u'测试test'
utf8_test='测试test'
gbk_test=unicode_test.encode('gbk')

#合并unicode和utf-8
merge=unicode_test+utf8_test
print type(merge)
print repr(merge)

#合并unicode和gbk
merge=unicode_test+gbk_test
print type(merge)
print repr(merge)
print merge

#合并utf-8和gbk
merge=utf8_test+gbk_test
print type(merge)
print repr(merge)
print merge

这里定义三个分别是unicode,utf-8和gbk编码的字符串,unicode_test,utf8_test和gbk_test
1.合并unicode和utf-8的时候,输出:

<type 'unicode'>
u'\u6d4b\u8bd5test\u6d4b\u8bd5test'

合并的结果的编码是unicode编码。
2.合并unicode和gbk,会报错:

'utf8' codec can't decode byte 0xb2 in position 0: invalid start byte

所以我们可以推测:
在python对两个字符串进行操作的时候,如果这两个字符串有一个是unicode编码,有一个是非unicode编码,python会将非unicode编码的字符串decode成unicode编码,再进行字符串操作
例如合并字符串的操作可以写成以下的function:

def merge_str(str1, str2):
    if isinstance(str1, unicode) and not isinstance(str2, unicode):
        str2 = str2.decode(sys.getdefaultencoding())
    elif not isinstance(str1, unicode) and isinstance(str2, unicode):
        str1 = str1.decode(sys.getdefaultencoding())
    return str1 + str2

PS:sys.getdefaultencoding()的初始值是ascii
所以,
codec can't encode(decode) characters这个报错是encode或decode这两个方法产生的,而这个方法的参数是sys.getdefaultencoding()。如果用ascii编码对带有中文的字符串进行解码,就会报错。所以修改系统的默认编码可以避免这个报错。
当执行str操作时,python会执行unicode_test.encode(sys.getdefaultencoding()) ,所以也会报错。

3.#合并utf-8和gbk的时候却不会报错,python会直接把两个字符串合并,不会有decode或encode的操作,但是输出的时候,部分字符串会乱码。
demo4.py

# encoding=gbk
import sys

reload(sys)
sys.setdefaultencoding('utf-8')
unicode_test = u'测试test'
utf8_test = unicode_test.encode('utf-8')
gbk_test = unicode_test.encode('gbk')

merge = utf8_test + gbk_test
print type(merge)
print repr(merge)
print merge

这里文件的encoding是gbk,sys.getdefaultencoding()设置为utf-8,结果是:

<type 'str'>
'\xe6\xb5\x8b\xe8\xaf\x95test\xb2\xe2\xca\xd4test'
测试test����test

即gbk的部分乱码了。所以输出的时候会按照sys.getdefaultencoding()的编码来解码。

三、怎么判断一个字符串的编码方式

  1. 没有办法准确地判断一个字符串的编码方式,例如gbk的“\aa”代表甲,utf-8的“\aa”代表乙,如果给定“\aa”怎么判断是哪种编码?它既可以是gbk也可以是utf-8

  2. 我们能做的是粗略地判断一个字符串的编码方式,因为上面的例如的情况是很少的,更多的情况是gbk中的'\aa'代表甲,utf-8中是乱码,例如�,这样我们就能判断'\aa'是gbk编码,因为如果用utf-8编码去解码的结果是没有意义的

  3. 而我们经常遇到的编码其实主要的就只有三种:utf-8,gbk,unicode

  • unicode一般是\u带头的,然后后面跟四位数字或字符串,例如 \u6d4b\u8bd5,一个\u对应一个汉字

  • utf-8一般是\x带头的,后面跟两位字母或数字,例如\xe6\xb5\x8b\xe8\xaf\x95\xe5\x95\x8a,三个\x代表一个汉字

  • gbk一般是\x带头的,后面跟两位字母或数字,例如\xb2\xe2\xca\xd4\xb0\xa1,两个个\x代表一个汉字

<完>

(作者:Xjng 来源:http://www.cnblogs.com/Xjng/p/5093905.html)

公益传播测试知识、技能与正能量!感谢作者!
分享测试生活,思考测试人生!欢迎投稿!
文章图片来自网络,如有侵权请见谅,请联系我们妥善处理。
735821166@qq.com

光荣之路
软件测试培训


官网:www.gloryroad.cn

微信公众号:gloryroadtrain

性能测试QQ群:415987441
测试招聘QQ群: 203715128
自动化3群QQ: 371211499

Python群:457561756

 
光荣之路 更多文章 今天晚上的 linux 公开课- Awk 编程 7月28日(今天)晚上的 linux 公开课- shell编程 8月4日(今天)晚上的 linux 公开课- shell编程 9月1日(本周一)晚8点半,光荣之路Web自动化系列基础课—javascript第二讲 推荐本好书《与机器赛跑》
猜您喜欢 新技术焦虑症?来这里拿药 ~~ H5性能优化方案 聊聊高并发之隔离术 C++11新特性Part7 卓越精英奖获得者:刘凤