解码非Unicode格式
我想让我的函数接收一个参数,这个参数可以是一个unicode对象或者是一个utf-8编码的字符串。在我的函数内部,我想把这个参数转换成unicode格式。我有这样的代码:
def myfunction(text):
if not isinstance(text, unicode):
text = unicode(text, 'utf-8')
...
我想知道有没有办法不使用isinstance这个检查方式?我希望能有一种更灵活的方式来处理。
在我尝试解码的过程中,我遇到了Python的一些奇怪行为。例如:
>>> u'hello'.decode('utf-8')
u'hello'
>>> u'cer\xf3n'.decode('utf-8')
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in po
sition 3: ordinal not in range(128)
或者
>>> u'hello'.decode('utf-8')
u'hello' 12:11
>>> unicode(u'hello', 'utf-8')
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: decoding Unicode is not supported
顺便说一下,我使用的是Python 2.6版本。
2 个回答
我不知道有什么好的方法可以避免在你的函数里使用 isinstance
检查,但也许其他人会知道。我可以指出你提到的两个奇怪的地方是因为你在做一些不太合理的事情:试图把已经解码成Unicode的东西再解码成Unicode。
第一个应该像这样,这样可以把那个字符串的UTF-8编码解码成Unicode版本:
>>> 'cer\xc3\xb3n'.decode('utf-8')
u'cer\xf3n'
而你的第二个应该像这样(不要使用 u''
的Unicode字符串字面量):
>>> unicode('hello', 'utf-8')
u'hello'
你可以试着用'utf-8'这个编码来解码,如果不行的话,就直接返回这个对象。
def myfunction(text):
try:
text = unicode(text, 'utf-8')
except TypeError:
return text
print(myfunction(u'cer\xf3n'))
# cerón
当你拿一个unicode对象并用它的decode
方法加上'utf-8'
编码时,Python会先尝试把这个unicode对象转换成字符串对象,然后再调用字符串对象的decode('utf-8')方法。
有时候,从unicode对象转换成字符串对象会失败,因为Python2默认使用ascii编码。
所以,一般来说,尽量不要尝试去解码unicode对象。如果非要尝试的话,最好把它放在一个try..except块里。虽然在Python2中,有一些编码方式可以成功解码unicode对象(见下面),但这些在Python3中已经被去掉了。
你可以查看这个Python的bug讨论,里面有关于这个问题的有趣讨论,还有Guido van Rossum的博客:
"我们正在采用一种稍微不同的编码方式:在Python 2中,编码可以接受unicode或8位字节作为输入,并可以输出任意一种,而在Python 3中,编码总是从一个unicode(文本)字符串转换成字节数组,解码则是反向操作。这意味着我们不得不去掉一些不符合这个模型的编码方式,比如rot13、base64和bz2(这些转换仍然被支持,只是不能通过encode/decode的API来实现)。"