我有以下代码。最后一行抛出错误。那是为什么?
class Foo(object):
def __unicode__(self):
return u'\u6797\u89ba\u6c11\u8b1d\u51b0\u5fc3\u6545\u5c45'
def __str__(self):
return self.__unicode__().encode('utf-8')
print "this works %s" % (u'asdf')
print "this works %s" % (Foo(),)
print "this works %s %s" % (Foo(), 'asdf')
print
print "this also works {0} {1}".format(Foo(), u'asdf')
print
print "this should break %s %s" % (Foo(), u'asdf')
错误是" UnicodeDecode错误:' ascii'编解码器不能解码位置18中的字节0xe6:序数不在范围内(128)"
答案 0 :(得分:3)
您正在混合unicode,字节字符串和自定义对象,并且您正在触发一系列无法混合的编码和解码。
在这种情况下,您的Foo()
值会被插值为字符串(str(Foo())
被使用),u'asdf'
插值会触发模板的解码到目前为止(使用UTF-8 Foo()
值)来插入unicode字符串。此解码失败,因为ASCII编解码器无法解码已插入的\xe6\x9e\x97
UTF-8字节序列。
在混合类型之前,您应始终将Unicode值显式编码为字节串或将字节字符串解码为Unicode,因为极端情况很复杂。
明确转换为unicode()
有效:
>>> print "this should break %s %s" % (unicode(Foo()), u'asdf')
this should break 林覺民謝冰心故居 asdf
因为输出变成了unicode字符串:
>>> "this should break %s %s" % (unicode(Foo()), u'asdf')
u'this should break \u6797\u89ba\u6c11\u8b1d\u51b0\u5fc3\u6545\u5c45 asdf'
,否则你最终得到一个字节串:
>>> "this should break %s %s" % (Foo(), 'asdf')
'this should break \xe6\x9e\x97\xe8\xa6\xba\xe6\xb0\x91\xe8\xac\x9d\xe5\x86\xb0\xe5\xbf\x83\xe6\x95\x85\xe5\xb1\x85 asdf'
(请注意,asdf
也是一个字节字符串。)
或者,使用unicode 模板:
>>> u"this should break %s %s" % (Foo(), u'asdf')
u'this should break \u6797\u89ba\u6c11\u8b1d\u51b0\u5fc3\u6545\u5c45 asdf'