【问题标题】:Decoding if it's not unicode如果不是 unicode 则解码
【发布时间】:2011-04-20 22:36:39
【问题描述】:

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

【问题讨论】:

标签: python unicode encoding utf-8


【解决方案1】:

您可以尝试使用“utf-8”编解码器对其进行解码,如果不起作用,则返回该对象。

def myfunction(text):
    try:
        text = unicode(text, 'utf-8')
    except TypeError:
        return text

print(myfunction(u'cer\xf3n'))
# cerón

当你获取一个 unicode 对象并使用 'utf-8' 编解码器调用它的 decode 方法时,Python 首先尝试将 unicode 对象转换为字符串对象,然后调用字符串对象的 decode('utf-8' ) 方法。

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

    • 奇怪的想法是 unicode 对象有一个 decode 方法。更奇怪的是,该方法有时有效,有时无效。与 unicode() 调用相同。
    • 好吧,API 肯定有些奇怪,因为使用 Unicode 字符串且未指定编码对 unicode 的调用将始终有效,而使用任何指定编码的调用将始终失败。
    猜你喜欢
    • 2022-09-23
    • 2013-12-02
    • 1970-01-01
    • 2021-11-16
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    相关资源
    最近更新 更多