是否可以构造utf-8编解码器无法编码的unicode字符串?

时间:2016-12-19 21:35:36

标签: python python-2.7 unicode utf-8

是否可以构造utf-8编解码器无法编码的unicode字符串?

从文档(https://docs.python.org/2/library/codecs.html)可以看出,utf-8编解码器可以在"任何语言"中编码符号。文档还会注意到编解码器只能编码某些字符或仅编码基本多语言平面。我不知道这是否等同于说"然而,使用unicode编解码器"无法构造无法转换为字节串的utf-8值。

这是utf-8编解码器的表格条目。

  

编解码器别名目的

     

utf_8 U8,UTF,utf8所有语言

这里的动机是我有一个实用程序函数,它接受一个unicode字符串或一个字节字符串并将其转换为字节字符串。给定一个字节字符串时,它是一个无操作。除非使用非字符串类型调用此函数,否则不应该抛出异常,并且在这种情况下,它应该使用稍后将被捕获并记录的TypeError信息失败。 (如果我们尝试插入到异常消息中的项目的repr太大,我们仍会遇到问题,但现在让我们忽略它。)

我正在使用strict设置,因为我希望此函数在遇到无法编码的unicode对象时抛出异常,但我希望这不可能

def utf8_to_bytes(item):
    """take a bytes or unicode object and convert it to bytes,
    using utf-8 if necessary"""
    if isinstance(item, bytes):
        return item
    elif isinstance(item, unicode):
        return codecs.encode(item, 'utf-8', 'strict')
    else:
        raise TypeError("item must be bytes or unicode. got %r" % type(item))

1 个答案:

答案 0 :(得分:2)

UTF-8旨在编码所有Unicode标准。将Unicode文本编码为UTF-8通常不会引发异常。

来自Wikipedia article on the codec

  

UTF-8是一种字符编码,能够编码由Unicode

定义的所有可能的字符或代码点

Python 2 UTF-8编码没有我所知道的边缘情况;非BMP数据和代理对的处理方式相同:

>>> import sys
>>> hex(sys.maxunicode)  # a narrow UCS-2 build
'0xffff'
>>> len(u'\U0001F525')
2
>>> u'\U0001F525'.encode('utf-8')
'\xf0\x9f\x94\xa5'
>>> u'\ud83d\udd25'
u'\U0001f525'
>>> len(u'\ud83d\udd25')
2
>>> u'\ud83d\udd25'.encode('utf-8')
'\xf0\x9f\x94\xa5'

请注意strict是默认编码模式。您也不需要使用codecs模块,只需使用encode对象上的unicode方法:

return item.encode('utf-8')

在Python 3中,情况稍微复杂一些。解码和编码surrogate pairs受到限制;官方标准规定这些字符应该只出现在UTF-16编码数据中,然后才出现在低和高对中。

因此,您需要明确声明要使用surrogatepass error handler支持此类代码点:

  

允许代理代码的编码和解码。这些编解码器通常将代理项的存在视为错误。

surrogatepassstrict之间的唯一区别是surrogatepass将允许您将Unicode文本中的任何代理代码点编码为UTF-8。您只能在极少数情况下获得此类数据(定义为文字,或者在UTF-16中意外丢弃此类代码点未配对,然后使用surrogatepass进行解码)。

因此,在Python 3中,只有在您可能使用surrogatepass解码或文字数据生成Unicode文本的情况下,您才需要使用{ {1}}绝对可以确定所有可能的Unicode值都可以编码。