如何在Python中使用代理对?

时间:2016-07-01 13:55:31

标签: python python-3.x unicode surrogate-pairs

这是Converting to Emoji的后续行动。在那个问题中,OP有一个json.dumps()编码的文件,表情符号代表一对表情符号\ud83d\ude4f。他/她在阅读文件和正确翻译表情符号时遇到问题,并且文件中每一行的answer都是json.loads(),而json模块将处理来自代理人的转换配对(我假设是UTF8编码的)表情符号。

所以这是我的情况:说我只有一个普通的Python 3 unicode字符串,里面有一个代理项:

emoji = "This is \ud83d\ude4f, an emoji."

如何处理此字符串以获取emoji的表示?我希望得到这样的东西:

"This is , an emoji."
# or
"This is \U0001f64f, an emoji."

我试过了:

print(emoji)
print(emoji.encode("utf-8")) # also tried "ascii", "utf-16", and "utf-16-le"
json.loads(emoji) # and `.encode()` with various codecs

通常我会收到与UnicodeEncodeError: XXX codec can't encode character '\ud83d' in position 8: surrogates no allowed类似的错误。

我在Linux上运行Python 3.5.1,$LANG设置为en_US.UTF-8。我已经在命令行的Python解释器和Sublime Text中运行的IPython中运行这些示例 - 似乎没有任何差异。

2 个答案:

答案 0 :(得分:28)

您在磁盘上的json文件中混合了一个文字字符串\ud83d(六个字符:\ u d 8 3 d)和一个单个字符u'\ud83d'(使用内存中的Python源代码中的字符串文字。这是Python 3上len(r'\ud83d') == 6len('\ud83d') == 1之间的区别。

如果您看到'\ud83d\ude4f' Python字符串( 2 字符),则上游存在错误。通常,你不应该得到这样的字符串。如果你得到一个,你就无法修复产生它的上游;你可以使用surrogatepass错误处理程序修复它:

>>> "\ud83d\ude4f".encode('utf-16', 'surrogatepass').decode('utf-16')
''

Python 2 was more permissive

注意:即使您的json文件包含文字\ ud83d \ ude4f( 12 字符);你不应该得到代理对:

>>> print(ascii(json.loads(r'"\ud83d\ude4f"')))
'\U0001f64f'

注意:结果是 1 字符('\U0001f64f'),而不是代理对('\ud83d\ude4f')。

答案 1 :(得分:4)

因为这是一个反复出现的问题,并且错误消息有些模糊,所以这里有更详细的说明。

代理人是一种表示比U + FFFF大的Unicode代码点的方法。

回想一下,Unicode最初被指定为包含65,536个字符,但是很快发现这不足以容纳世界上所有的字形。

作为(否则为固定宽度)UTF-16编码的扩展机制,保留区被设置为包含用于表达Basic Multilingual Plane之外的代码点的机制:此特殊代码中的任何代码点区域之后必须是来自同一区域的另一个字符代码,并且它们一起将表示一个数字点,该数字大于旧限制。

(严格来说,代孕区域分为两半;成对的第一个代孕需要来自高代孕的一半,而第二个代孕则来自低代孕的人。)

这是一种专门支持UTF-16编码的旧机制,不应在其他编码中使用。

换句话说,虽然U+12345可以用代理对U + D808 U + DF45表示,但您应该直接直接表达它。

更详细地讲,这是如何在UTF-8中将其表示为单个字符:

0xF0 0x92 0x8D 0x85

这是相应的代理序列:

0xED 0xA0 0x88
0xED 0xBD 0x85

如已接受的答案中已经建议的那样,您可以使用类似的东西来往返

>>> "\ud808\udf45".encode('utf-16', 'surrogatepass').decode('utf-16').encode('utf-8')
b'\xf0\x92\x8d\x85'

也许也请参阅http://www.russellcottrell.com/greek/utilities/surrogatepaircalculator.htm