python的一个编解码错误
发表于2012/10/24由latlontude
(1)出错的代码
这里的字符串格式化默认是先把每个对象转换为unicode的 (这里是按照a,b的类型进行判断确认最终输出字符串的编码,如果a,b都没有显式声明为unicode,则最终转换的类型为编码为sys.getdefaultencoding()得到的字符集,否则如果a/b任意一个为unicode类型,则最终转换为类型为unicode字符串) 。
转换时调用对象的decode方法, 除非显示声明字符串对象为unicode编码,否则系统认为默认的编码方式是sys.getdefaultencoding(),这里是ascii(0~128)。即转换时会调用obj.decode(“ascii”),将obj字符串转换为unicode。
这样对于1中的情形,a本身显式声明为unicode,不用转换,b会调用 b.decode(“ascii”)来转换为unicode对象. 对于2中的情形,b显式声明为unicode,不用转换,a会调用a.decode(“ascii”).
本文测试时,终端使用的编码方式是utf-8,这样2中a的utf8编码和ascii编码一样,这样转换为unciode就不会出错。而1中的b的包含中文,由于终端为utf8,实质b是utf8编码的,其编码的字节序中有超过0x7f的字节,这样在利用ascii来解码就会有不能识别的字符,这样就会报错“ ‘ascii’ codec can’t decode byte 0xe8 in position 0: ordinal not in range(128)”。
补充:
可以这样设置
另外如果:
查看b的二进制: 显然都是utf-8编码的。(0xe8/0xe6….)
发表于2012/10/24由latlontude
(1)出错的代码
>>> a = u"test"
>>> b = "这些一看就"
>>> c = "%s:%s"%(a,b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128)
(2)没有出错的代码
>>> b = u"这些一看就"
>>> a = "test"
>>> c = "%s:%s"%(a,b)
两者有什么区别呢?
这里的字符串格式化默认是先把每个对象转换为unicode的 (这里是按照a,b的类型进行判断确认最终输出字符串的编码,如果a,b都没有显式声明为unicode,则最终转换的类型为编码为sys.getdefaultencoding()得到的字符集,否则如果a/b任意一个为unicode类型,则最终转换为类型为unicode字符串) 。
转换时调用对象的decode方法, 除非显示声明字符串对象为unicode编码,否则系统认为默认的编码方式是sys.getdefaultencoding(),这里是ascii(0~128)。即转换时会调用obj.decode(“ascii”),将obj字符串转换为unicode。
这样对于1中的情形,a本身显式声明为unicode,不用转换,b会调用 b.decode(“ascii”)来转换为unicode对象. 对于2中的情形,b显式声明为unicode,不用转换,a会调用a.decode(“ascii”).
本文测试时,终端使用的编码方式是utf-8,这样2中a的utf8编码和ascii编码一样,这样转换为unciode就不会出错。而1中的b的包含中文,由于终端为utf8,实质b是utf8编码的,其编码的字节序中有超过0x7f的字节,这样在利用ascii来解码就会有不能识别的字符,这样就会报错“ ‘ascii’ codec can’t decode byte 0xe8 in position 0: ordinal not in range(128)”。
补充:
可以这样设置
import sys
reload(sys)
sys.setdefaultencoding('utf8')
即使系统的默认编码为utf8,而非ascii码。这样1中的错误也不会出现了。
另外如果:
>>> a = "test"
>>> b = "这样在利用"
>>> c = "%s:%s"%(a,b)
>>> print type(c)
<type 'str'>
也不会报错,因为a/b系统默认都是ascii的编码。只是b由于终端设置为utf-8才显示为中文。这里就不会调用unicode来编码了。虽然b的字符值超过了0x7f。
查看b的二进制: 显然都是utf-8编码的。(0xe8/0xe6….)
>>> b = "这样在利用"
>>> import binascii
>>> binascii.b2a_hex(b)
'e8bf99e6a0b7e59ca8e588a9e794a8'