解码,如果它不是unicode

时间:2010-10-04 17:47:28

标签: python unicode encoding utf-8

我希望我的函数接受一个可能是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 个答案:

答案 0 :(得分:18)

您可以尝试使用'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对象转换为字符串对象,然后调用字符串对象的解码(' utf-8')方法。

有时从unicode对象到字符串对象的转换失败,因为Python2默认使用ascii编解码器。

因此,一般来说,永远不要尝试解码unicode对象。或者,如果必须尝试,请将其捕获到try..except块中。可能有一些编解码器解码unicode对象在Python2中工作(见下文),但它们已在Python3中删除。

有关此问题的有趣讨论,请参阅此Python bug ticket, 还有Guido van Rossum's blog

  

“我们采用的略有不同   编解码器的方法:在Python 2中,   编解码器可以接受Unicode或   8位作为输入并产生为   输出,在Py3k中,编码总是一个   从Unicode(文本)翻译   字符串到一个字节数组,和   解码总是相反的   方向。这意味着我们必须这样做   删除一些不适合的编解码器   这个模型,例如rot13,base64   和bz2(那些转换仍然是   支持,只是不通过   编码/解码API)。“

答案 1 :(得分:0)

我不知道有什么好方法可以避免isinstance检查你的功能,但也许其他人会这样做。我可以指出,你引用的两个奇怪之处是因为你正在做一些没有意义的事情:尝试将已解码为Unicode的Unicode解码。

第一个应该是这样的,它将该字符串的UTF-8编码解码为Unicode版本:

>>> 'cer\xc3\xb3n'.decode('utf-8')
u'cer\xf3n'

你的第二个应该是这样的(不使用u'' Unicode字符串文字):

>>> unicode('hello', 'utf-8')
u'hello'